package main

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"math/rand"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/garyburd/redigo/redis"
	"github.com/wtf/mahjong/model"
	"github.com/wtf/mahjong/utils"
	"github.com/xlstudio/wxbizdatacrypt"
)

var locksss sync.Mutex

type loginData struct {
	Code     string `json:"code"`
	UniqueId string `json:"uniqueid"`
	Channel  string `json:"channel"`
	Version  string `json:"versions"`
}

type updateData struct {
	UserId  int    `json:"userId"`
	Level   int    `json:"level"`
	Time    int    `json:"time"`
	Find    int    `json:"find"`
	Restore int    `json:"restore"`
	Isnew   int    `json:"isnew"`
	Isvideo int    `json:"isvideo"`
	Sign    string `json:"sign"`
}

type updateData1 struct {
	UserId  int    `json:"userId"`
	Level   int    `json:"level"`
	Gem     int    `json:"gem"`
	Isnew   int    `json:"isnew"`
	Iscoin  int    `json:"iscoin"`
	Time    int    `json:"time"`
	Isvideo int    `json:"isvideo"`
	Balance int    `json:"balance"`
	Sign    string `json:"sign"`
}

type datacrypt struct {
	EncryptedData string `json:"encryptedData"`
	Iv            string `json:"iv"`
	OpenId        string `json:"uniqueid"`
}

type videoD struct {
	OpenId string `json:"uniqueid"`
}

type signinD struct {
	OpenId string `json:"uniqueid"`
	Gem    int    `json:"gem"`
	Time   int    `json:"time"`
	Iscoin int    `json:"iscoin"`
	Sign   string `json:"sign"`
}

type shareClickD struct {
	OpenId    string `json:"uniqueid"`
	ShareCode string `json:"shareCode"`
}

type Rank struct {
	OpenId string `json:"uniqueid"`
}

type DownRedis struct {
	Start int `json:"start"`
	End   int `json:"end"`
}

type OpenScene struct {
	OpenId  string `json:"uniqueid"`
	SceneId int    `json:"sceneId"`
	Coin    int    `json:"coin"`
}

type BuyProp struct {
	OpenId  string `json:"uniqueid"`
	SceneId int    `json:"sceneId"`
	PropId  int    `json:"propId"`
	Level   int    `json:"level"`
	Coin    int    `json:"coin"`
}

type SwitchProp struct {
	OpenId  string `json:"uniqueid"`
	SceneId int    `json:"sceneId"`
	PropId  int    `json:"propId"`
	Level   int    `json:"level"`
}

/*
*
登录接口 未授权仅含有code channel
@param code nickName xx xx
*/
func login(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "login:没有收到登录数据")
	if err != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	var loginD loginData
	err1 := json.Unmarshal(body, &loginD)

	utils.CheckErr(write, err1, 101, "login:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	var openId string
	var err2 error

	if loginD.Code != "" {
		// 去微信获取openId以及unionId
		openId, _, err2 = model.OpenIdByCode(loginD.Code)
		utils.CheckErr(write, err2, 102, "login:获取微信openId失败")
		if err2 != nil {
			utils.Info(loginD)
			return
		}
	} else {
		openId = loginD.UniqueId
	}

	if openId == "" {
		utils.CheckErr(write, errors.New("openId不能为空"), 1033, "login:openId不能为空")
		return
	}

	// 根据openId判断用户是否注册
	var userId, level, gem, collect, month int
	var shareCode string
	ok, err := model.Check(openId)
	var click = 0
	var news = 0
	var signin = 0
	var balance = 0
	// var errMonth error
	var (
		scene1     []int
		scene2     []int
		scene3     []int
		sceneUse1  []int
		sceneUse2  []int
		sceneUse3  []int
		newVersion int
		coin       int
		eight      int
		// errEight   error
	)

	var channel = "ldt"
	var versions = "1.0.0"
	if strings.Count(loginD.Version, ".") == 2 && len(loginD.Version) <= 11 {
		versions = loginD.Version
	}

	if ok == false {

		// -注册用户
		channel = loginD.Channel
		tempTime := int(time.Now().Unix())
		user := model.User{
			UniqueId:      openId,
			Channel:       loginD.Channel,
			Time:          tempTime,
			LastLoginTime: tempTime,
			Gem:           20,
			Coin:          0,
			Version:       versions,
		}

		userId, err = user.Create()
		utils.CheckErr(write, err, 103, "login:新建用户失败")
		if err != nil {
			return
		}

		// 生成shareCode存入redis md5(openId+userId)
		w := md5.New()
		io.WriteString(w, openId+strconv.Itoa(userId))
		shareCode = fmt.Sprintf("%x", w.Sum(nil))
		_, resErr := rc.Do("HMSET", utils.Config.PkgName+"-shareCode_list", shareCode, userId)

		utils.CheckErr(write, resErr, 105, "login:添加shareCode redis失败")
		if resErr != nil {
			return
		}

		// 添加排行榜
		_, rankErr := rc.Do("ZADD", utils.Config.PkgName+"_rank", 0, openId)

		utils.CheckErr(write, rankErr, 106, "login:注册新排行榜失败")
		if rankErr != nil {
			return
		}

		level = 0
		click = 1
		news = 1
		gem = user.Gem
		coin = user.Coin
		collect = 0
		month = 0
		eight = 0

		// 新建食物数据
		foodServer := model.NewFoodServer()
		foodInfo := model.FoodList{
			OpenId:    openId,
			Stock:     "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
			Level:     1,
			Opened:    0,
			Completes: "0,0,0,0,0",
			TaskLevel: "0,0,0",
			TaskData:  "0,0,0",
		}

		err = foodServer.Create(&foodInfo)
		// 如果有错误记录
		if err != nil {
			utils.Error(err)
		}
	} else {
		// 查询用户user_id
		user, err := model.UserByUniqueId(openId)

		utils.CheckErr(write, err, 104, "login:没有查询到用户信息")
		if err != nil {
			return
		}

		userId = user.Id
		channel = user.Channel
		balance = user.Icon

		// 更新最后一次登录时间
		tempUser := model.User{UniqueId: user.UniqueId}
		errxx := tempUser.Update("lastLoginTime", strconv.Itoa(int(time.Now().Unix())))
		utils.CheckErr(write, errxx, 114, "login:更新登录时间失败")

		// 更新版本
		errx1 := tempUser.Update("versions", versions)
		utils.CheckErr(write, errx1, 114, "login:更新登录版本号失败")

		w := md5.New()
		io.WriteString(w, openId+strconv.Itoa(userId))
		shareCode = fmt.Sprintf("%x", w.Sum(nil))
		rootUserId, err3 := redis.Int(rc.Do("HGET", utils.Config.PkgName+"-shareCode_list", shareCode))
		if rootUserId == 0 || err3 != nil {
			// utils.Info("update shareCode ", user.UniqueId)
			_, _ = rc.Do("HMSET", utils.Config.PkgName+"-shareCode_list", shareCode, userId)
		}

		// level	获取关卡数
		var rdsErr error
		level, rdsErr = redis.Int(rc.Do("zscore", utils.Config.PkgName+"_rank", openId))

		// utils.CheckErr(write, rdsErr, 103, "login:获取分数失败"+openId)
		if rdsErr != nil {
			level = user.Levels
		}

		// 查询昨天的分享是否有人点击
		/*clickTime, err := redis.Int(rc.Do("zscore", utils.Config.PkgName+"-click", user.Id))
		if err == nil {
			if clickTime >= getYesd() {
				click = 1
			}
		}*/
		gem = user.Gem
		coin = user.Coin
		collect = user.Collect
		newVersion = user.NewVersion

		// 判断是否签到
		timeNow := getNow()
		if user.Signtime == timeNow {
			signin = 1
		}

		/*if month, errMonth = checkMonth(user.UniqueId); errMonth != nil {
			utils.Error("检测月卡失败")
		}

		if eight, errEight = checkEight(user.UniqueId); errEight != nil {
			utils.Error("检测eight失败")
		}*/

		// todo  老用户,如果没有food数据,新建之
		foodServer := model.NewFoodServer()
		countFood := foodServer.Count(openId)
		if countFood <= 0 {
			foodInfo := model.FoodList{
				OpenId:    openId,
				Stock:     "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
				Level:     1,
				Opened:    0,
				Completes: "0,0,0,0,0",
				TaskLevel: "0,0,0",
				TaskData:  "0,0,0",
			}

			err = foodServer.Create(&foodInfo)
			// 如果有错误记录
			if err != nil {
				utils.Error(err)
			}
		}
	}

	userNew, err111 := model.UserByUniqueId(openId)
	utils.CheckErr(write, err111, 10455, "login:没有查询到用户信息")
	if err111 != nil {
		return
	}

	if userNew.SceneId1 == 0 {
		// 开启第一个场景
		sceneId, err00 := createScene1(openId)
		if err00 != nil {
			utils.CheckErr(write, err00, 1114, "login:开启场景1失败")
		} else {
			userNew.SceneId1 = sceneId
			_ = userNew.Update("scene_id_1", strconv.Itoa(sceneId))
		}
	}

	// 场景 如果场景存在,根据场景id查询道具信息
	if userNew.SceneId1 > 0 {
		scene := model.Scene{
			Id:        userNew.SceneId1,
			TableName: "scene_1",
		}
		err := scene.Get()
		if err != nil {
			utils.Error("获取场景1信息失败", err)
		} else {
			scene1 = append(scene1, scene.Prop1, scene.Prop2, scene.Prop3, scene.Prop4, scene.Prop5)
			sceneUse1 = append(sceneUse1, scene.Prop1Use, scene.Prop2Use, scene.Prop3Use, scene.Prop4Use, scene.Prop5Use)
		}
	}

	if userNew.SceneId2 > 0 {
		scene := model.Scene{
			Id:        userNew.SceneId2,
			TableName: "scene_2",
		}
		err := scene.Get()
		if err != nil {
			utils.Error("获取场景2信息失败")
		} else {
			scene2 = append(scene2, scene.Prop1, scene.Prop2, scene.Prop3, scene.Prop4, scene.Prop5)
			sceneUse2 = append(sceneUse2, scene.Prop1Use, scene.Prop2Use, scene.Prop3Use, scene.Prop4Use, scene.Prop5Use)
		}
	}

	if userNew.SceneId3 > 0 {
		scene := model.Scene{
			Id:        userNew.SceneId3,
			TableName: "scene_3",
		}
		err := scene.Get()
		if err != nil {
			utils.Error("获取场景3信息失败")
		} else {
			scene3 = append(scene3, scene.Prop1, scene.Prop2, scene.Prop3, scene.Prop4, scene.Prop5)
			sceneUse3 = append(sceneUse3, scene.Prop1Use, scene.Prop2Use, scene.Prop3Use, scene.Prop4Use, scene.Prop5Use)
		}
	}

	// var version string
	var check int
	check = 0
	// version = loginD.Version

	/*if strings.Count(version, ".") > 0 {
		var errx error

		check, errx = model.GetVersion(version)
		utils.CheckErr(write, errx, 104, "login:获取check失败")
		if errx != nil {
			return
		}
	}*/

	var isNew int
	isNew = checkIsNew(openId)
	var money = 0
	var amount = 0 // 福卡数量

	// 获取用户可提现红包金额
	/*if isNew == 1 {
		rows, errxxx := model.Db.Query("select id, amount from packet where type = 2 and unique_id = ?", openId)
		if errxxx == nil {
			for rows.Next() {
				redPacketRow := model.RedPacket{}
				errxx := rows.Scan(&redPacketRow.Id, &redPacketRow.Amount)
				if errxx != nil {
					utils.Error(errxx, "login:查询红包失败")
				}

				money += redPacketRow.Amount
			}
		}

		// 获取福卡数量
		sum, errx := model.GetRedSum(openId)
		if errx == nil {
			amount = sum
		}
	}*/
	click = 1
	var ad = 0    // 0:隐藏诗词一笔画特殊推荐 1:开启
	var pay = 0   // 在x关卡显示充值
	var price = 6 // 支付金额
	var days = 15 // 续费周期

	collect = 1

	// 获取食物数据
	var (
		stock      []string
		opened     bool
		storeLevel int
		completes  []bool
		taskLevel  []string
		taskData   []string
		foodLevel  int
	)

	foodServer := model.NewFoodServer()
	foodRow, err := foodServer.GetRow(openId)
	if err != nil {
		utils.Error(err)
	} else {
		stock = strings.Split(foodRow.Stock, ",")
		if foodRow.Opened == 1 {
			opened = true
		}
		storeLevel = foodRow.Level
		taskLevel = strings.Split(foodRow.TaskLevel, ",")
		taskData = strings.Split(foodRow.TaskData, ",")

		tmpCompletes := strings.Split(foodRow.Completes, ",")
		for _, val := range tmpCompletes {
			tmp := false
			if val == "1" {
				tmp = true
			}
			completes = append(completes, tmp)
		}

		foodLevel, _ = redis.Int(rc.Do("GET", utils.Config.PkgName+"_foodLevel_"+openId))
	}

	postLogin := model.PostLogin{
		UserId:     userId,
		ShareCode:  shareCode,
		Level:      level,
		OpenId:     openId,
		Check:      check,
		IsNew:      isNew,
		Money:      money,
		Click:      click,
		Amount:     amount,
		News:       news,
		Gem:        gem,
		Coin:       coin,
		Collect:    collect,
		Signin:     signin,
		Ad:         ad,
		Month:      month,
		Pay:        pay,
		Price:      price,
		Days:       days,
		Scene1:     scene1,
		Scene2:     scene2,
		Scene3:     scene3,
		SceneUse1:  sceneUse1,
		SceneUse2:  sceneUse2,
		SceneUse3:  sceneUse3,
		NewVersion: newVersion,
		Eight:      eight,
		Channel:    channel,
		Balance:    balance,
		Stock:      stock,
		Opened:     opened,
		StoreLevel: storeLevel,
		TaskData:   taskData,
		TaskLevel:  taskLevel,
		Completes:  completes,
		FoodLevel:  foodLevel,
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    postLogin,
	}
	returnDa.Returnfunc(write)
}

/*func level(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "level:没有收到更新的数据")
	if err != nil {
		return
	}

	utils.Info("level check")

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	updateD := updateData{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "level:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	if updateD.Isnew == 1 { // 新版本,验证秘钥
		// 解密验证
		w := md5.New()
		io.WriteString(w, strconv.Itoa(updateD.UserId)+strconv.Itoa(updateD.Level)+strconv.Itoa(updateD.Isnew)+strconv.Itoa(updateD.Isvideo)+strconv.Itoa(updateD.Time)+utils.Config.Key)
		newSign := fmt.Sprintf("%x", w.Sum(nil))
		if newSign != updateD.Sign {
			utils.Info(updateD, newSign)
			utils.CheckErr(write, errors.New("密钥认证失败"), 122, "level:密钥认证失败")
			return
		}
	}

	if updateD.UserId <= 0 {
		utils.CheckErr(write, errors.New("level:非法提交userId"), 110, "level:非法提交userId")
		return
	}

	openId, err := model.OpenIdByUserId(updateD.UserId)
	utils.CheckErr(write, err, 102, "level:userId错误")
	if err != nil {
		return
	}

	// level	获取level
	level, rdsErr := redis.Int(rc.Do("zscore", utils.Config.PkgName+"_rank", openId))
	utils.CheckErr(write, rdsErr, 103, "level:获取分数失败")
	if rdsErr != nil {
		return
	}

	if updateD.Level-level != 1 {
		returnDa := utils.ReturnData{
			Errcode: 104,
			Errmsg:  "关卡错误",
			Data: Map{
				"level": level,
			},
		}
		returnDa.Returnfunc(write)
		return
	}

	// 更新redis slices_rank(zset)  level(等级)  openId(用户)
	_, resErr := rc.Do("ZADD", utils.Config.PkgName+"_rank", updateD.Level, openId)
	utils.CheckErr(write, resErr, 105, "level:更新redis失败")
	if resErr != nil {
		return
	}

	userInfo, err33 := model.UserByUniqueId(openId)
	utils.CheckErr(write, err33, 133, "level:获取用户信息失败")
	if err33 != nil {
		return
	}

	// 同步数据库关卡
	if errxx := userInfo.Update("levels", strconv.Itoa(updateD.Level)); errxx != nil {
		utils.Warning("update database level error")
	}

	var (
		gemAll = 0
		gem    = 0
		err35  error
	)

	if updateD.Isnew == 1 {
		// 更新钻石
		gem = 10
		if updateD.Isvideo == 1 {
			gem *= 5
			if err34 := userInfo.Update("video_times", strconv.Itoa(userInfo.VideoTimes+1)); err34 != nil {
				utils.CheckErr(write, err34, 134, "level:video统计失败")
				return
			}
			// 过关翻倍
			if err888 := userInfo.Update("multiple", strconv.Itoa(userInfo.Multiple+1)); err888 != nil {
				utils.CheckErr(write, err888, 1088, "gem:multiple统计失败")
				return
			}
		}
		if gemAll, err35 = gemAct(openId, 1, gem); err35 != nil {
			utils.CheckErr(write, err35, 135, "level:更新钻石失败")
			return
		}
	}

	if updateD.Time > 0 {
		//记录过关时间
		//1.纵向记录同一关
		_, resErrs := rc.Do("ZADD", utils.Config.PkgName+"_level:"+strconv.Itoa(updateD.Level), updateD.Time, openId)
		utils.CheckErr(write, resErrs, 106, "level:纵向记录过关时间失败")
		if resErrs != nil {
			return
		}
		//2.横向记录个人所有关
		_, resErrss := rc.Do("ZADD", utils.Config.PkgName+"_level:"+openId, updateD.Time, updateD.Level)
		utils.CheckErr(write, resErrss, 107, "level:横向记录过关时间失败")
		if resErrss != nil {
			return
		}

		//记录过关使用道具数量
		//1.纵向记录同一道具
		_, resErrx := rc.Do("ZADD", utils.Config.PkgName+"_level-find:"+strconv.Itoa(updateD.Level), updateD.Find, openId)
		utils.CheckErr(write, resErrx, 108, "level-find:纵向记录find道具失败")
		if resErrx != nil {
			return
		}
		_, resErrq := rc.Do("ZADD", utils.Config.PkgName+"_level-restore:"+strconv.Itoa(updateD.Level), updateD.Restore, openId)
		utils.CheckErr(write, resErrq, 109, "level-restore:纵向记录restore道具失败")
		if resErrq != nil {
			return
		}

		//2.横向记录个人所有道具
		_, resErrqq := rc.Do("ZADD", utils.Config.PkgName+"_level-stage:"+openId, updateD.Find+updateD.Restore, updateD.Level)
		utils.CheckErr(write, resErrqq, 110, "level-stage:横向记录道具失败")
		if resErrqq != nil {
			return
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"gem":    gem,
			"gemAll": gemAll,
			"level":  updateD.Level,
		},
	}
	returnDa.Returnfunc(write)
}*/

/*
*
更新关卡
@param	userId	用户id
@param 	score	分数
@return errno
*/
func levelNew(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "levelNew:没有收到更新的数据")
	if err != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	updateD := updateData1{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "levelNew:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	if updateD.Isnew == 1 { // 验证秘钥
		// 解密验证
		w := md5.New()
		io.WriteString(w, strconv.Itoa(updateD.UserId)+strconv.Itoa(updateD.Level)+strconv.Itoa(updateD.Gem)+strconv.Itoa(updateD.Isnew)+strconv.Itoa(updateD.Isvideo)+strconv.Itoa(updateD.Iscoin)+strconv.Itoa(updateD.Time)+utils.Config.Key)
		newSign := fmt.Sprintf("%x", w.Sum(nil))
		if newSign != updateD.Sign {
			utils.Info(updateD, newSign)
			utils.CheckErr(write, errors.New("密钥认证失败"), 122, "levelNew:密钥认证失败")
			return
		}
	} else if updateD.Isnew == 2 { // 验证秘钥
		// utils.Info(updateD)
		// 解密验证
		w := md5.New()
		io.WriteString(w, strconv.Itoa(updateD.UserId)+strconv.Itoa(updateD.Level)+strconv.Itoa(updateD.Gem)+strconv.Itoa(updateD.Isnew)+strconv.Itoa(updateD.Balance)+strconv.Itoa(updateD.Time)+utils.Config.Key)
		newSign := fmt.Sprintf("%x", w.Sum(nil))
		if newSign != updateD.Sign {
			utils.Info(updateD, newSign)
			utils.CheckErr(write, errors.New("密钥认证失败"), 122, "levelNew:密钥认证失败")
			return
		}
	}

	if updateD.UserId <= 0 {
		utils.CheckErr(write, errors.New("level:非法提交userId"), 110, "levelNew:非法提交userId")
		return
	}

	openId, err := model.OpenIdByUserId(updateD.UserId)
	utils.CheckErr(write, err, 102, "levelNew:userId错误")
	if err != nil {
		return
	}

	// level	获取level
	level, rdsErr := redis.Int(rc.Do("zscore", utils.Config.PkgName+"_rank", openId))
	// utils.CheckErr(write, rdsErr, 103, "levelNew:获取分数失败")
	if rdsErr != nil {
		user, _ := model.UserByUniqueId(openId)
		level = user.Levels
	}

	if updateD.Level-level <= 0 {
		returnDa := utils.ReturnData{
			Errcode: 104,
			Errmsg:  "关卡错误",
		}
		returnDa.Returnfunc(write)
		return
	}

	// 更新redis slices_rank(zset)  level(等级)  openId(用户)
	_, resErr := rc.Do("ZADD", utils.Config.PkgName+"_rank", updateD.Level, openId)
	utils.CheckErr(write, resErr, 105, "levelNew:更新redis失败")
	if resErr != nil {
		return
	}

	userInfo, err33 := model.UserByUniqueId(openId)
	utils.CheckErr(write, err33, 133, "levelNew:获取用户信息失败")
	if err33 != nil {
		return
	}

	// 同步数据库关卡
	if errxx := userInfo.Update("levels", strconv.Itoa(updateD.Level)); errxx != nil {
		utils.Warning("update database level error")
	}

	err77 := userInfo.Update("coin", strconv.Itoa(updateD.Gem))
	utils.CheckErr(write, err77, 1077, "levelNew:更新金币失败")
	if err77 != nil {
		return
	}

	if updateD.Isnew == 2 {
		// 更新用户balance到db
		err77 := userInfo.Update("icon", strconv.Itoa(updateD.Balance))
		utils.CheckErr(write, err77, 1078, "levelNew:更新余额失败")
		if err77 != nil {
			return
		}
		// 2.新建api,获取三个好友以及余额
	}

	// 统计通关率
	// 更新redis incr diff_1
	_, resErr = rc.Do("INCR", utils.Config.PkgName+"_level_all_"+strconv.Itoa(updateD.Level))
	if resErr != nil {
		utils.Error("levelNew:update level_all error")
	}

	s := strconv.Itoa(getNow())
	_, err2 := rc.Do("ZINCRBY", utils.Config.PkgName+"_level_day_"+s, 1, updateD.Level)
	if err2 != nil {
		utils.Error("levelNew:update level_day error")
	}

	_, err3 := rc.Do("INCR", utils.Config.PkgName+"_levelCount_"+s)
	if err3 != nil {
		utils.Error("levelNew:update levelCount error")
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func encryptedData(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "encryptedData:没有收到解密的数据")
	if err != nil {
		return
	}
	cryptD := datacrypt{}
	err1 := json.Unmarshal(body, &cryptD)
	utils.CheckErr(write, err1, 101, "encryptedData:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	sessionKey, resErr := redis.String(rc.Do("GET", utils.Config.PkgName+"_session_key:"+cryptD.OpenId))
	utils.CheckErr(write, resErr, 102, "encryptedData:获取session_key失败")
	if resErr != nil {
		return
	}

	appId := utils.Config.AppId
	iv := cryptD.Iv
	encryptedData := cryptD.EncryptedData

	pc := wxbizdatacrypt.WxBizDataCrypt{AppID: appId, SessionKey: sessionKey}
	result, err3 := pc.Decrypt(encryptedData, iv, false) // 第三个参数解释： 需要返回 JSON 数据类型时 使用 true, 需要返回 map 数据类型时 使用 false
	utils.CheckErr(write, err3, 103, "encryptedData:解密失败")
	if err3 != nil {
		return
	}

	data := result.(map[string]interface{})

	var unionId string
	switch x := data["unionId"].(type) {
	case string:
		unionId = string(x)
	}

	// 获取关注用的wegame_openId-unionId hash
	if unionId != "" {
		_, rdsErr := redis.String(rc.Do("HGET", "wegame_openId-unionId", cryptD.OpenId))
		if rdsErr != nil {
			_, resErr := rc.Do("HSET", "wegame_openId-unionId", cryptD.OpenId, unionId)
			if resErr != nil {
				utils.Error(resErr, "encryptedData:wegame_openId-unionId添加失败")
			}
		}

		// 将union_id更新到users表
		user, err30 := model.UserByUniqueId(cryptD.OpenId)
		if err30 == nil {
			if user.UnionId == "" {
				users := model.User{UniqueId: cryptD.OpenId}
				err31 := users.Update("union_id", unionId)
				if err31 != nil {
					utils.Error(err31, "encryptedData:用户unionId更新失败")
				}
			}
		}
	}

	var name, head_img string
	switch x := data["nickName"].(type) {
	case string:
		name = string(x)
	}
	switch x := data["avatarUrl"].(type) {
	case string:
		head_img = string(x)
	}

	// 获取用户的用户信息
	if head_img != "" {
		user, err := model.UserByUniqueId(cryptD.OpenId)

		utils.CheckErr(write, err, 104, "encryptedData:没有查询到用户信息")
		if err != nil {
			return
		}

		if user.HeadImg == "" { // 更新头像和姓名
			newUser := model.User{
				UniqueId: cryptD.OpenId,
			}
			_ = newUser.Update("head_img", head_img)
			_ = newUser.Update("name", UnicodeEmojiCode(name))
		}
	}
}

// 表情转换
func UnicodeEmojiCode(s string) string {
	ret := ""
	rs := []rune(s)
	for i := 0; i < len(rs); i++ {
		if len(string(rs[i])) == 4 {
			u := `[\u` + strconv.FormatInt(int64(rs[i]), 16) + `]`
			ret += u

		} else {
			ret += string(rs[i])
		}
	}
	return ret
}

// 表情解码
func UnicodeEmojiDecode(s string) string {
	// emoji表情的数据表达式
	re := regexp.MustCompile("\\[[\\\\u0-9a-zA-Z]+\\]")
	// 提取emoji数据表达式
	reg := regexp.MustCompile("\\[\\\\u|]")
	src := re.FindAllString(s, -1)
	for i := 0; i < len(src); i++ {
		e := reg.ReplaceAllString(src[i], "")
		p, err := strconv.ParseInt(e, 16, 32)
		if err == nil {
			s = strings.Replace(s, src[i], string(rune(p)), -1)
		}
	}
	return s
}

func checkIsNew(openId string) (isNew int) {

	isNew = 0
	users, err := model.UserByUniqueId(openId)
	if err == nil {
		t, _ := time.ParseInLocation("2006-01-02 15:04:05", utils.Config.RedTime, time.Local)
		if users.Time >= int(t.Unix()) {
			isNew = 1
		}
	}
	return
}

func getNow() int {
	t := time.Now()
	today := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).Unix()
	return int(today)
}

func getTime() int {
	return int(time.Now().Unix())
}

func getYesd() int {
	t := time.Now().AddDate(0, 0, -1)
	today := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).Unix()
	return int(today)
}

func rankWorld(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "rankWorld:没有收到解密的数据")
	if err != nil {
		return
	}
	rankD := Rank{}
	err1 := json.Unmarshal(body, &rankD)
	utils.CheckErr(write, err1, 101, "rankWorld:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	userInfo, err2 := model.UserByUniqueId(rankD.OpenId)
	utils.CheckErr(write, err2, 102, "rankWorld:没有查询到用户信息")
	if err2 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	// list	redis.zrevrange(game + 'rank', 0, 19, "withscores")获取前二十名用户 倒叙
	rankList, err3 := redis.Strings(rc.Do("zrevrange", utils.Config.PkgName+"_rank", 0, 19, "withscores"))
	utils.CheckErr(write, err3, 103, "rankWorld:获取排行榜失败")
	if err3 != nil {
		return
	}
	// self	redis.zrevrank(game + 'rank', openId)	返回自己的名次		倒叙
	selfRank, err4 := redis.Int64(rc.Do("zrevrank", utils.Config.PkgName+"_rank", userInfo.UniqueId))
	utils.CheckErr(write, err4, 104, "rankWorld:获取排行榜self失败")
	if err4 != nil {
		return
	}

	selfRank += 1

	// level
	level, err6 := redis.Int(rc.Do("zscore", utils.Config.PkgName+"_rank", userInfo.UniqueId))
	utils.CheckErr(write, err6, 106, "login:获取分数失败"+userInfo.UniqueId)
	if err6 != nil {
		return
	}

	newList := make(map[int]Map)
	var j = 0
	var userName string
	var headImg string

	// 根据rankList获取该玩家的uniqueId name headImg
	for i := 0; i < len(rankList); i += 2 {
		// 查找用户
		/*if rankList[i] == "oyL_q4g1vMQpWSSRBR0yoada802Q" {
			continue
		}*/
		userInfo1, err5 := model.UserByUniqueId(rankList[i])
		utils.CheckErr(write, err5, 105, "rank:获取用户信息失败")
		if err5 != nil {
			return
		}
		temp, _ := strconv.Atoi(rankList[i+1])

		if userInfo1.Name == "" {
			userName = "游戏玩家"
		} else {
			userName = UnicodeEmojiDecode(userInfo1.Name)
		}

		if userInfo1.HeadImg == "" {
			headImg = "http://h5static.ledongtian.com/games/wegameresource/mahjong/noname.png"
		} else {
			headImg = userInfo1.HeadImg
		}

		newList[j] = Map{
			"name":    userName,
			"headImg": headImg,
			"score":   temp,
			"rank":    int(math.Floor(float64(i/2)) + 1),
		}
		j++
	}

	var name string
	if userInfo.Name == "" {
		name = "unknown"
	} else {
		name = UnicodeEmojiDecode(userInfo.Name)
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"list": newList,
			"self": Map{
				"name":    name,
				"headImg": userInfo.HeadImg,
				"score":   level,
				"rank":    selfRank,
			},
		},
	}
	returnDa.Returnfunc(write)
}

func openScene(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "openScene:没有收到更新的数据")
	if err != nil {
		return
	}

	openSceneData := OpenScene{}
	err1 := json.Unmarshal(body, &openSceneData)
	utils.CheckErr(write, err1, 101, "openScene:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	userInfo, err2 := model.UserByUniqueId(openSceneData.OpenId)
	utils.CheckErr(write, err2, 102, "openScene:获取用户信息失败")
	if err2 != nil {
		return
	}

	sceneErr := false
	// sceneCoin := 0
	switch openSceneData.SceneId {
	case 1:
		if userInfo.SceneId1 > 0 {
			sceneErr = true
		}
	case 2:
		if userInfo.SceneId2 > 0 {
			sceneErr = true
		}
		// sceneCoin = 500
	case 3:
		if userInfo.SceneId3 > 0 {
			sceneErr = true
		}
		// sceneCoin = 1000
	default:
		utils.CheckErr(write, errors.New("未知场景"), 103, "openScene:未知场景")
		return
	}

	if sceneErr == true {
		utils.CheckErr(write, errors.New("该场景已经开启"), 103, "openScene:该场景已经开启")
		return
	}

	/*if userInfo.Coin < sceneCoin {
		utils.CheckErr(write, errors.New("金币不足"), 104, "openScene:金币不足")
		return
	}*/

	if err5 := userInfo.Update("coin", strconv.Itoa(openSceneData.Coin)); err5 != nil {
		utils.CheckErr(write, err5, 106, "openScene:扣除金币失败")
		return
	}

	scene := model.Scene{
		OpenId:    userInfo.UniqueId,
		Time:      int(time.Now().Unix()),
		TableName: "scene_" + strconv.Itoa(openSceneData.SceneId),
	}

	id, err3 := scene.Create()
	utils.CheckErr(write, err3, 105, "openScene:开启场景失败")
	if err3 != nil {
		return
	}

	switch openSceneData.SceneId {
	case 1:
		_ = userInfo.Update("scene_id_1", strconv.Itoa(id))
	case 2:
		_ = userInfo.Update("scene_id_2", strconv.Itoa(id))
	case 3:
		_ = userInfo.Update("scene_id_3", strconv.Itoa(id))
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    make([]int, 5),
	}
	returnDa.Returnfunc(write)
}

func buyProp(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "buyProp:没有收到更新的数据")
	if err != nil {
		return
	}

	openSceneData := BuyProp{}
	err1 := json.Unmarshal(body, &openSceneData)
	utils.CheckErr(write, err1, 101, "buyProp:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	userInfo, err2 := model.UserByUniqueId(openSceneData.OpenId)
	utils.CheckErr(write, err2, 102, "buyProp:获取用户信息失败")
	if err2 != nil {
		return
	}

	sceneErr := false
	id := 0

	switch openSceneData.SceneId {
	case 1:
		if userInfo.SceneId1 == 0 {
			sceneErr = true
		} else {
			id = userInfo.SceneId1
		}
	case 2:
		if userInfo.SceneId2 == 0 {
			sceneErr = true
		} else {
			id = userInfo.SceneId2
		}
	case 3:
		if userInfo.SceneId3 == 0 {
			sceneErr = true
		} else {
			id = userInfo.SceneId3
		}
	default:
		utils.CheckErr(write, errors.New("未知场景"), 103, "buyProp:未知场景")
		return
	}

	if sceneErr == true {
		utils.CheckErr(write, errors.New("该场景未开启"), 103, "buyProp:该场景未开启")
		return
	}

	scene := model.Scene{
		Id:        id,
		TableName: "scene_" + strconv.Itoa(openSceneData.SceneId),
	}

	err4 := scene.Get()
	utils.CheckErr(write, err4, 105, "buyProp:查询场景失败")
	if err4 != nil {
		return
	}

	if err7 := userInfo.Update("coin", strconv.Itoa(openSceneData.Coin)); err7 != nil {
		utils.CheckErr(write, err7, 107, "buyProp:扣除金币失败")
		return
	}

	err3 := scene.Set("prop_"+strconv.Itoa(openSceneData.PropId), openSceneData.Level)
	utils.CheckErr(write, err3, 104, "buyProp:购买道具失败")
	if err3 != nil {
		return
	}

	err6 := scene.Set("prop_"+strconv.Itoa(openSceneData.PropId)+"_use", openSceneData.Level)
	utils.CheckErr(write, err6, 106, "buyProp:设置使用道具失败")
	if err6 != nil {
		return
	}

	err5 := scene.Get()
	utils.CheckErr(write, err5, 105, "buyProp:查询场景失败")
	if err5 != nil {
		return
	}

	var scenes []int
	scenes = append(scenes, scene.Prop1, scene.Prop2, scene.Prop3, scene.Prop4, scene.Prop5)

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    scenes,
	}
	returnDa.Returnfunc(write)
}

func switchProp(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "switchProp:没有收到更新的数据")
	if err != nil {
		return
	}

	openSceneData := SwitchProp{}
	err1 := json.Unmarshal(body, &openSceneData)
	utils.CheckErr(write, err1, 101, "switchProp:无法解析更新的json数据")
	if err1 != nil {
		return
	}
	// utils.Info(openSceneData, string(body))
	userInfo, err2 := model.UserByUniqueId(openSceneData.OpenId)
	utils.CheckErr(write, err2, 102, "switchProp:获取用户信息失败")
	if err2 != nil {
		return
	}

	sceneErr := false
	id := 0
	switch openSceneData.SceneId {
	case 1:
		if userInfo.SceneId1 == 0 {
			sceneErr = true
		} else {
			id = userInfo.SceneId1
		}
	case 2:
		if userInfo.SceneId2 == 0 {
			sceneErr = true
		} else {
			id = userInfo.SceneId2
		}
	case 3:
		if userInfo.SceneId3 == 0 {
			sceneErr = true
		} else {
			id = userInfo.SceneId3
		}
	default:
		utils.CheckErr(write, errors.New("未知场景"), 103, "switchProp:未知场景")
		return
	}

	if sceneErr == true {
		utils.CheckErr(write, errors.New("该场景未开启"), 103, "switchProp:该场景未开启")
		return
	}

	scene := model.Scene{
		Id:        id,
		TableName: "scene_" + strconv.Itoa(openSceneData.SceneId),
	}

	err4 := scene.Get()
	utils.CheckErr(write, err4, 105, "switchProp:查询场景失败")
	if err4 != nil {
		return
	}

	propVal := 0
	switch openSceneData.PropId {
	case 1:
		propVal = scene.Prop1
	case 2:
		propVal = scene.Prop2
	case 3:
		propVal = scene.Prop3
	case 4:
		propVal = scene.Prop4
	case 5:
		propVal = scene.Prop5
	}

	if propVal == 0 || openSceneData.Level > propVal {
		utils.CheckErr(write, errors.New("请先购买或升级物品"), 103, "switchProp:请先购买或升级物品")
		return
	}

	if openSceneData.Level == 0 {
		utils.CheckErr(write, errors.New("参数错误"), 1033, "switchProp:参数错误")
		return
	}

	err3 := scene.Set("prop_"+strconv.Itoa(openSceneData.PropId)+"_use", openSceneData.Level)
	utils.CheckErr(write, err3, 104, "switchProp:切换道具失败")
	if err3 != nil {
		return
	}

	err5 := scene.Get()
	utils.CheckErr(write, err5, 105, "switchProp:查询场景失败")
	if err5 != nil {
		return
	}

	var scenes []int
	scenes = append(scenes, scene.Prop1Use, scene.Prop2Use, scene.Prop3Use, scene.Prop4Use, scene.Prop5Use)

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    scenes,
	}
	returnDa.Returnfunc(write)
}

/*func checkIsNewx(write http.ResponseWriter, request *http.Request) {

	utils.Info("checkIsNewx check")

	vars := request.URL.Query()
	OpenId := vars["openId"][0]
	var isNew int
	isNew = 0
	users, err := model.UserByUniqueId(OpenId)
	if err == nil {
		t, _ := time.ParseInLocation("2006-01-02 15:04:05", utils.Config.RedTime, time.Local)
		if users.Time >= int(t.Unix()) {
			isNew = 1
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    isNew,
	}
	returnDa.Returnfunc(write)
}

func checkMonthx(write http.ResponseWriter, request *http.Request) {

	utils.Info("checkMonthx check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "checkMonthx:没有收到更新的数据")
	if err != nil {
		return
	}

	updateD := videoD{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "checkMonthx:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	var month = 0
	var errMonth error
	if updateD.OpenId != "" {
		if month, errMonth = checkMonth(updateD.OpenId); errMonth != nil {
			utils.Error("检测月卡失败")
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"month": month,
		},
	}
	returnDa.Returnfunc(write)
}

func video(write http.ResponseWriter, request *http.Request) {

	utils.Info("video check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "video:没有收到更新的数据")
	if err != nil {
		return
	}

	updateD := videoD{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "video:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	if updateD.OpenId != "" {

		userInfo, err2 := model.UserByUniqueId(updateD.OpenId)
		if err2 == nil {
			times := userInfo.VideoTimes + 1
			_ = userInfo.Update("video_times", strconv.Itoa(times))
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func dailyClick(write http.ResponseWriter, request *http.Request) {
	utils.Info("dailyClick check")

	body, err := ioutil.ReadAll(request.Body)
	utils.CheckErr(write, err, 100, "dailyClick:无法获取body信息")
	defer request.Body.Close()
	if err != nil {
		return
	}

	user_shareCodeD := shareClickD{}
	err = json.Unmarshal(body, &user_shareCodeD)
	utils.CheckErr(write, err, 101, "dailyClick:无法解析body信息")
	if err != nil {
		return
	}

	if user_shareCodeD.ShareCode == "" {
		utils.CheckErr(write, errors.New("shareCode为空"), 102, "dailyClick:shareCode为空")
		return
	}

	if user_shareCodeD.OpenId == "" {
		utils.CheckErr(write, errors.New("OpenId为空"), 103, "dailyClick:OpenId为空")
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	// 根据user_shareCode查询宿主userId
	rootUserId, err := redis.Int(rc.Do("HGET", utils.Config.PkgName+"-shareCode_list", user_shareCodeD.ShareCode))
	utils.CheckErr(write, err, 103, "dailyClick:查询shareCode用户id失败")
	if err != nil {
		return
	}

	userInfo, err := model.UserByUniqueId(user_shareCodeD.OpenId)
	utils.CheckErr(write, err, 104, "dailyClick:获取用户信息失败")
	if err != nil {
		return
	}

	// 查询mahjong-click
	if rootUserId != userInfo.Id {

		key := utils.Config.PkgName + "-click"
		_, _ = rc.Do("zadd", key, int(time.Now().Unix()), rootUserId)
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func addCard(write http.ResponseWriter, request *http.Request) {

	utils.Info("addCard check")

	// 获取参数
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "addCard:没有收到数据")
	if err != nil {
		return
	}

	var addRedPacketD addRedPacketData
	err1 := json.Unmarshal(body, &addRedPacketD)

	utils.CheckErr(write, err1, 101, "addCard:无法解析json数据")
	if err1 != nil {
		return
	}

	var openId string
	var level int
	openId = addRedPacketD.OpenId
	level = addRedPacketD.Level

	// 解密验证
	w := md5.New()
	io.WriteString(w, openId+strconv.Itoa(level)+strconv.Itoa(addRedPacketD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != addRedPacketD.Sign {
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "addCard:密钥认证失败")
		return
	}

	var amount = 0
	var count = 0
	var err3 error
	// 第一次,第二次获得福卡80~120
	// 老用户获得8~12
	// 当用户余额>=18时,每次给1
	count, err3 = model.GetRedCount(addRedPacketD.OpenId)
	if err3 != nil {
		count = 0
	}
	if count < 2 {
		amount = randCard(1)
	} else {
		amount = randCard(0)

		sum, err4 := model.GetRedSum(addRedPacketD.OpenId)
		if err4 == nil && sum >= 1800 {
			amount = 1
		}
	}

	redPacket := model.RedPacket{
		UniqueId: openId,
		Level:    level,
		Time:     int(time.Now().Unix()),
		Type:     4,
		Amount:   amount,
	}
	_, err5 := redPacket.Create()
	utils.CheckErr(write, err5, 105, "addCard:新建红包失败")
	if err5 != nil {
		return
	}

	sum, err6 := model.GetRedSum(addRedPacketD.OpenId)
	utils.CheckErr(write, err6, 106, "addCard:获取总福卡失败")
	if err6 != nil {
		return
	}

	// 返回红包码
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: map[string]int{
			"amount": sum,
		},
	}
	returnDa.Returnfunc(write)
}


func prop2gem(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "prop2gem:没有收到数据")
	if err != nil {
		return
	}

	var gemD Prop2gem
	err1 := json.Unmarshal(body, &gemD)
	utils.CheckErr(write, err1, 101, "prop2gem:无法解析json数据")
	if err1 != nil {
		return
	}

	// 解密验证
	w := md5.New()
	io.WriteString(w, gemD.OpenId+strconv.Itoa(gemD.Num)+strconv.Itoa(gemD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != gemD.Sign {
		utils.Info(gemD, newSign)
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "prop2gem:密钥认证失败")
		return
	}

	// 获取用户信息
	userInfo, err3 := model.UserByUniqueId(gemD.OpenId)
	utils.CheckErr(write, err3, 103, "prop2gem:获取用户信息失败")
	if err3 != nil {
		return
	}

	var (
		gemAll = 0
		gem    = 0
		err5   error
	)

	gem = gemD.Num

	if gem <= 0 {
		utils.CheckErr(write, errors.New("更新钻石数量错误"), 104, "prop2gem:更新钻石数量错误")
		return
	}

	if gemAll, err5 = gemAct(userInfo.UniqueId, 1, gem); err5 != nil {
		utils.CheckErr(write, err5, 105, "prop2gem:添加钻石失败")
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"gem":    gem,
			"gemAll": gemAll,
		},
	}
	returnDa.Returnfunc(write)
}

func inviteCard(write http.ResponseWriter, request *http.Request) {
	utils.Info("inviteCard check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "inviteCard:没有收到解密的数据")
	if err != nil {
		return
	}
	friendD := Friend{}
	err1 := json.Unmarshal(body, &friendD)
	utils.CheckErr(write, err1, 101, "inviteCard:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	if friendD.ShareCode == "" {
		utils.CheckErr(write, errors.New("用户信息不能为空"), 102, "inviteCard:用户信息不能为空")
		return
	}

	if friendD.OpenId == "" {
		utils.CheckErr(write, errors.New("好友信息不能为空"), 103, "inviteCard:好友信息不能为空")
		return
	}

	// 获取好友用户信息
	friendInfo, err4 := model.UserByUniqueId(friendD.OpenId)
	utils.CheckErr(write, err4, 104, "inviteCard:获取好友用户信息失败")
	if err4 != nil {
		return
	}

	// 判断是否为新玩家
	var now = int(time.Now().Unix())
	if (now - friendInfo.Time) > 3 {
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
		}
		returnDa.Returnfunc(write)
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	// 根据user_shareCode查询宿主userId
	rootUserId, err5 := redis.Int(rc.Do("HGET", utils.Config.PkgName+"-shareCode_list", friendD.ShareCode))
	utils.CheckErr(write, err5, 105, "inviteCard:查询shareCode用户id失败")
	if err5 != nil {
		return
	}

	userInfo, err6 := model.UserById(rootUserId)
	utils.CheckErr(write, err6, 106, "inviteCard:获取用户信息失败")
	if err6 != nil {
		return
	}

	if userInfo.UniqueId == friendD.OpenId {
		utils.CheckErr(write, errors.New("自己不能邀请自己"), 107, "inviteCard:自己不能添加自己为好友")
		return
	}

	// 添加action
	// 添加宿主信息
	err8 := inviteAction(userInfo, friendInfo)

	// 如果有错误记录
	if err8 != nil {
		utils.Error(err8)
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func inviteCardList(write http.ResponseWriter, request *http.Request) {
	utils.Info("inviteCardList check")
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "inviteCardList:没有收到解密的数据")
	if err != nil {
		return
	}
	inviteD := videoD{}
	err1 := json.Unmarshal(body, &inviteD)
	utils.CheckErr(write, err1, 101, "inviteCardList:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	// 获取邀请数据
	inviteTodayInfo, err2 := model.InviteGetByIdTime(inviteD.OpenId, getNow())
	if err2 != nil { // 没有今日数据
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
			Data:    Map{},
		}
		returnDa.Returnfunc(write)
		return
	}

	var inviteList = make(map[int]Map)

	inviteArr := strings.Split(inviteTodayInfo.Invite, ",")
	isGetArr := strings.Split(inviteTodayInfo.IsGet, ",")

	for k, v := range inviteArr {
		userInfo, err3 := model.UserByUniqueId(v)
		if err3 != nil {
			utils.CheckErr(write, err3, 103, "inviteCardList:获取用户信息失败")
		}
		isGet, _ := strconv.Atoi(isGetArr[k])

		inviteList[k] = Map{
			"id":     k,
			"isGet":  isGet,
			"avatar": userInfo.HeadImg,
		}
	}

	// 判断是否可以显示/提现第六个红包
	if len(inviteArr) >= 5 {
		inviteList[5] = Map{
			"id":     5,
			"isGet":  inviteTodayInfo.IsGetLast,
			"avatar": "",
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    inviteList,
	}
	returnDa.Returnfunc(write)
}

func inviteCardGet(write http.ResponseWriter, request *http.Request) {
	utils.Info("inviteCardGet check")
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "inviteCardGet:没有收到解密的数据")
	if err != nil {
		return
	}
	inviteD := model.PowerGet{}
	err1 := json.Unmarshal(body, &inviteD)
	utils.CheckErr(write, err1, 101, "inviteCardGet:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	// 获取邀请数据
	inviteTodayInfo, err2 := model.InviteGetByIdTime(inviteD.OpenId, getNow())
	utils.CheckErr(write, err2, 102, "inviteCardGet:邀请记录不存在")
	if err2 != nil {
		return
	}

	inviteArr := strings.Split(inviteTodayInfo.Invite, ",")
	isGetArr := strings.Split(inviteTodayInfo.IsGet, ",")

	// 判断是否满足提现第六个红包
	if inviteD.Id == 5 && len(inviteArr) == 5 {
		// 检测是否已经领取
		if inviteTodayInfo.IsGetLast == 1 {
			utils.CheckErr(write, errors.New("红包已领取"), 111, "inviteCardGet:红包已领取")
			return
		}
		// 提现0.5元
		// todo
		// openId获取unionId
		unionId, err22 := model.UnionIdByUniqueId(inviteD.OpenId)
		utils.CheckErr(write, err22, 122, "inviteCardGet:无法获取用户信息")
		if err22 != nil {
			return
		}

		if unionId == "" {
			utils.CheckErr(write, errors.New("unionId获取失败, 请重新授权"), 110, "inviteCardGet:请点击开始游戏同意授权")
			return
		}

		// 请求php提现
		resp, err44 := http.Get("http://gc-api.ledongtian.com/gamecenter/public/api/drawGameActWGFK?openId=" + inviteD.OpenId + "&unionId=" + unionId + "&gameid=1")
		utils.CheckErr(write, err44, 144, "inviteCardGet:无法获取接口信息")
		if err44 != nil {
			return
		}

		defer resp.Body.Close()
		body, err55 := ioutil.ReadAll(resp.Body)
		utils.CheckErr(write, err55, 155, "inviteCardGet:无法获取接口data信息")
		if err55 != nil {
			return
		}

		response := drawRedPacketResponse{}
		err66 := json.Unmarshal(body, &response)
		utils.CheckErr(write, err66, 166, "inviteCardGet:无法解析body信息")
		if err66 != nil {
			return
		}

		// 判断是否提现成功
		if response.Code != 0 {
			utils.CheckErr(write, errors.New(response.Msg), 110, response.Msg)
			return
		} else {
			returnDa := utils.ReturnData{
				Errcode: 0,
				Errmsg:  response.Msg,
			}
			returnDa.Returnfunc(write)
			return
		}
	}

	// 领取其他
	// 检测是否已被领取
	if isGetArr[inviteD.Id] == "1" {
		utils.CheckErr(write, errors.New("福卡已领取"), 105, "inviteCardGet:福卡已领取")
		return
	}

	// 设置已领取
	isGetArr[inviteD.Id] = "1"

	// 创建福卡红包
	var count = 20
	redPacket := model.RedPacket{
		UniqueId: inviteD.OpenId,
		Level:    0,
		Time:     int(time.Now().Unix()),
		Type:     4,
		Amount:   count,
	}
	_, err6 := redPacket.Create()
	utils.CheckErr(write, err6, 106, "inviteCardGet:领取福卡失败")
	if err6 != nil {
		return
	}

	// 更新领取记录标识
	inviteTodayInfo.IsGet = strings.Replace(strings.Trim(fmt.Sprint(isGetArr), "[]"), " ", ",", -1)
	err7 := model.InviteUpdateInvite(inviteTodayInfo)
	utils.CheckErr(write, err7, 107, "inviteCardGet:更新领取标识失败")
	if err7 != nil {
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func gem(write http.ResponseWriter, request *http.Request) {

	utils.Info("gem check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "gem:没有收到数据")
	if err != nil {
		return
	}

	var gemD Gem
	err1 := json.Unmarshal(body, &gemD)
	utils.CheckErr(write, err1, 101, "gem:无法解析json数据")
	if err1 != nil {
		return
	}
	// utils.Info("repeatCheck: gem=", gemD.OpenId, gemD.Act)
	// 解密验证
	w := md5.New()
	io.WriteString(w, gemD.OpenId+gemD.Act+strconv.Itoa(gemD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != gemD.Sign {
		utils.Info(gemD, newSign)
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "gem:密钥认证失败")
		return
	}

	// 获取用户信息
	userInfo, err3 := model.UserByUniqueId(gemD.OpenId)
	utils.CheckErr(write, err3, 103, "gem:获取用户信息失败")
	if err3 != nil {
		return
	}

	var (
		gemAll = 0
		gem    = 0
		err5   error
	)

	switch gemD.Act {
	case "back":
		gem = 30
		if gemAll, err5 = gemAct(userInfo.UniqueId, -1, gem); err5 != nil {
			utils.CheckErr(write, err5, 105, "gem:back失败")
			return
		}
		if err8 := userInfo.Update("back", strconv.Itoa(userInfo.Back+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gem:back统计失败")
			return
		}
		break
	case "search":
		gem = 30
		if gemAll, err5 = gemAct(userInfo.UniqueId, -1, gem); err5 != nil {
			utils.CheckErr(write, err5, 105, "gem:search失败")
			return
		}
		if err8 := userInfo.Update("search", strconv.Itoa(userInfo.Search+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gem:search统计失败")
			return
		}
		break
	case "bomb":
		gem = 30
		if gemAll, err5 = gemAct(userInfo.UniqueId, -1, gem); err5 != nil {
			utils.CheckErr(write, err5, 105, "gem:bomb失败")
			return
		}
		if err8 := userInfo.Update("bomb", strconv.Itoa(userInfo.Bomb+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gem:bomb统计失败")
			return
		}
		break
	case "ext":
		gem = 30
		if gemAll, err5 = gemAct(userInfo.UniqueId, -1, gem); err5 != nil {
			utils.CheckErr(write, err5, 105, "gem:ext失败")
			return
		}
		if err8 := userInfo.Update("ext", strconv.Itoa(userInfo.Ext+1)); err8 != nil {
			utils.CheckErr(write, err8, 108, "gem:ext统计失败")
			return
		}
		break
	case "collect":
		gem = 200
		if userInfo.Collect == 1 {
			utils.Info(gemD)
			utils.CheckErr(write, errors.New("已经收藏"), 106, "gem:已经收藏")
			return
		}
		if err7 := userInfo.Update("collect", strconv.Itoa(1)); err7 != nil {
			utils.CheckErr(write, err7, 107, "gem:更新collect失败")
			return
		}
		if gemAll, err5 = gemAct(userInfo.UniqueId, 1, gem); err5 != nil {
			utils.CheckErr(write, err5, 105, "gem:collect失败")
			return
		}
		break
	default:
		utils.CheckErr(write, errors.New("操作无法识别"), 104, "gem:操作无法识别")
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"gem":    gem,
			"gemAll": gemAll,
		},
	}
	returnDa.Returnfunc(write)
}

*/

/*func addRedPacket(write http.ResponseWriter, request *http.Request) {
	// 获取参数
	utils.Info("addRedPacket check")
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "addRedPacket:没有收到数据")
	if err != nil {
		return
	}

	var addRedPacketD addRedPacketData
	err1 := json.Unmarshal(body, &addRedPacketD)

	utils.CheckErr(write, err1, 101, "addRedPacket:无法解析json数据")
	if err1 != nil {
		return
	}

	var openId string
	var level int
	openId = addRedPacketD.OpenId
	level = addRedPacketD.Level

	// 解密验证
	w := md5.New()
	io.WriteString(w, openId+strconv.Itoa(level)+strconv.Itoa(addRedPacketD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != addRedPacketD.Sign {
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "addRedPacket:密钥认证失败")
		return
	}

	// 检测该level是否重复生成红包
	idx, err4 := model.RedByLevel(openId, level)
	if err4 == nil && idx > 0 {
		utils.CheckErr(write, errors.New("该关卡已经有红包"), 104, "addRedPacket:该关卡已经有红包")
		return
	}

	// 插入数据库 红包码 = md5(openId+time)
	w1 := md5.New()
	io.WriteString(w1, openId+strconv.Itoa(addRedPacketD.Time))
	redCode := fmt.Sprintf("%x", w1.Sum(nil))

	redPacket := model.RedPacket{
		UniqueId: openId,
		Level:    level,
		RedCode:  redCode,
		Time:     int(time.Now().Unix()),
		GetTime:  0,
		Friend:   "",
		Type:     0,
		Amount:   0,
	}
	_, err3 := redPacket.Create()
	utils.CheckErr(write, err3, 103, "addRedPacket:新建红包失败")
	if err3 != nil {
		return
	}

	// 返回红包码
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    addRedPacketReD{RedCode: redCode},
	}
	returnDa.Returnfunc(write)
}

func getRedPacket(write http.ResponseWriter, request *http.Request) {

	utils.Info("getRedPacket check")

	// 获取参数
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "getRedPacket:没有收到数据")
	if err != nil {
		return
	}

	var getRedPacketD getRedPacketData
	err1 := json.Unmarshal(body, &getRedPacketD)

	utils.CheckErr(write, err1, 101, "getRedPacket:无法解析json数据")
	if err1 != nil {
		return
	}

	// 查出所有红包列表
	rows, err2 := model.Db.Query("select id, amount, type, friend, redCode, level from packet where unique_id = ?", getRedPacketD.OpenId)
	utils.CheckErr(write, err2, 102, "getRedPacket:还没有红包")
	if err2 != nil {
		return
	}

	returnD := make(map[int]interface{})
	var headImg, name string
	var money int = 0
	for rows.Next() {
		redPacketRow := model.RedPacket{}
		err3 := rows.Scan(&redPacketRow.Id, &redPacketRow.Amount, &redPacketRow.Type, &redPacketRow.Friend, &redPacketRow.RedCode, &redPacketRow.Level)
		utils.CheckErr(write, err3, 103, "getRedPacket:查询红包失败")
		if err3 != nil {
			return
		}

		if redPacketRow.Type == 2 {
			money += redPacketRow.Amount
		}

		if redPacketRow.Type == 3 {
			continue
		}

		// 返回内容: redCode, amount, 好友头像,红包类型  以及总可提现数
		// 查询好友头像
		headImg = ""
		name = ""
		if redPacketRow.Friend != "" {
			if redPacketRow.Friend == "ldt" { // 系统赠送红包
				headImg = "http://h5static.ledongtian.com/games/wegameresource/mahjong/ldt.png"
				name = "互助红包"
			} else {
				user, err4 := model.UserByUniqueId(redPacketRow.Friend)
				utils.CheckErr(write, err4, 104, "getRedPacket:查询用户信息失败")
				if err4 != nil {
					return
				}

				if user.HeadImg == "" {
					headImg = "http://h5static.ledongtian.com/games/wegameresource/mahjong/noname.png"
				} else {
					headImg = user.HeadImg
				}

				if user.Name == "" {
					name = "未授权人"
				} else {
					name = UnicodeEmojiDecode(user.Name)
				}
			}
		}
		returnD[redPacketRow.Id] = tempPacket{
			RedCode: redPacketRow.RedCode,
			Amount:  redPacketRow.Amount,
			Type:    redPacketRow.Type,
			HeadImg: headImg,
			Name:    name,
			Level:   redPacketRow.Level,
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: getRedPacketDataRe{
			List:  returnD,
			Money: money,
		},
	}
	returnDa.Returnfunc(write)
}

func helpRedPacket(write http.ResponseWriter, request *http.Request) {

	utils.Info("helpRedPacket check")

	// 获取参数
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "helpRedPacket:没有收到数据")
	if err != nil {
		return
	}

	var helpRedPacketD helpRedPacketData
	err1 := json.Unmarshal(body, &helpRedPacketD)

	utils.CheckErr(write, err1, 101, "helpRedPacket:无法解析json数据")
	if err1 != nil {
		return
	}

	// 解密验证
	w := md5.New()
	io.WriteString(w, helpRedPacketD.OpenId+helpRedPacketD.RedCode+strconv.Itoa(helpRedPacketD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != helpRedPacketD.Sign {
		utils.CheckErr(write, errors.New("密钥认证失败"), 102, "helpRedPacket:密钥认证失败")
		return
	}
	// 获取红包信息 判断红包是否存在并且有效
	redRow, err3 := model.RedByCode(helpRedPacketD.RedCode)
	utils.CheckErr(write, err3, 103, "helpRedPacket:获取红包信息失败")
	if err3 != nil {
		return
	}

	// 排除自己给自己开启红包
	if redRow.UniqueId == helpRedPacketD.OpenId {
		utils.CheckErr(write, errors.New("自己不能开启自己的红包"), 111, "helpRedPacket:自己不能开启自己的红包")
		return
	}

	if redRow.Type != 0 {
		utils.CheckErr(write, errors.New("红包已经被开启"), 153, "helpRedPacket:红包已经被开启")
		return
	}
	// 判断好友新老用户+随机金钱
	user, err4 := model.UserByUniqueId(helpRedPacketD.OpenId)
	utils.CheckErr(write, err4, 104, "helpRedPacket:获取好友信息失败")
	if err4 != nil {
		return
	}

	var money, isNew int
	if int(time.Now().Unix())-user.Time <= 6 { // 新用户
		money = randMoney(1)
		isNew = 1
	} else {
		money = randMoney(0)
		isNew = 0
	}

	// 更新红包内容
	statement := "UPDATE packet SET amount = ?, type = ?, friend = ?, getTime = ? WHERE id = ?"
	stmt, err5 := model.Db.Prepare(statement)
	utils.CheckErr(write, err5, 105, "helpRedPacket:更新红包错误1")
	if err5 != nil {
		return
	}
	defer stmt.Close()

	_, err6 := stmt.Exec(money, 1, helpRedPacketD.OpenId, int(time.Now().Unix()), redRow.Id)
	utils.CheckErr(write, err6, 106, "helpRedPacket:更新红包错误2")
	if err6 != nil {
		return
	}

	// 返回好友以及自己获得的红包金额
	var friendMoney int = 0
	if isNew == 1 { // 新用户
		friendMoney = randMoney(1)
	} else { // 老用户
		temp := checkIsNew(helpRedPacketD.OpenId)
		if temp == 1 { // 新红包用户
			friendMoney = randMoney(2)
		} else { // 假红包用户
			friendMoney = 0
		}
	}
	returnD := inviteRedReturn{
		Self:    money,
		Friend:  friendMoney,
		RedCode: "",
		Name:    "互助红包",
		HeadImg: "http://h5static.ledongtian.com/games/wegameresource/mahjong/ldt.png",
	}
	// 添加好友获得的红包
	// 插入数据库 红包码 = md5(openId+time)
	if friendMoney > 0 {
		w1 := md5.New()
		io.WriteString(w1, helpRedPacketD.OpenId+strconv.Itoa(helpRedPacketD.Time))
		redCode := fmt.Sprintf("%x", w1.Sum(nil))

		tempTime := int(time.Now().Unix())
		redPacket := model.RedPacket{
			UniqueId: helpRedPacketD.OpenId,
			Level:    0,
			RedCode:  redCode,
			Amount:   friendMoney,
			Type:     1,
			Time:     tempTime,
			GetTime:  tempTime,
			Friend:   "ldt",
		}
		_, err7 := redPacket.Create()
		if err7 != nil {
			utils.Error(err7, "helpRedPacket:新建好友红包失败")
		}
		returnD.RedCode = redCode
	}

	// 返回信息
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    returnD,
	}
	returnDa.Returnfunc(write)
}

func insertRedPacket(write http.ResponseWriter, request *http.Request) {

	utils.Info("insertRedPacket check")

	// 获取参数
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "insertRedPacket:没有收到数据")
	if err != nil {
		return
	}

	var insertRedPacketD insertRedPacketData
	err1 := json.Unmarshal(body, &insertRedPacketD)

	utils.CheckErr(write, err1, 101, "insertRedPacket:无法解析json数据")
	if err1 != nil {
		return
	}

	// 获取红包信息 判断红包是否存在并且有效
	redRow, err2 := model.RedByCode(insertRedPacketD.RedCode)
	utils.CheckErr(write, err2, 102, "insertRedPacket:获取红包信息失败")
	if err2 != nil {
		return
	}

	if redRow.Type != 1 {
		utils.CheckErr(write, errors.New("红包状态错误,不能被领取"), 103, "insertRedPacket:红包状态错误,不能被领取")
		return
	}

	// 更新红包内容
	statement := "UPDATE packet SET type = ?, insertTime = ? WHERE id = ?"
	stmt, err4 := model.Db.Prepare(statement)
	utils.CheckErr(write, err4, 104, "insertRedPacket:更新红包错误1")
	if err4 != nil {
		return
	}
	defer stmt.Close()

	_, err5 := stmt.Exec(2, int(time.Now().Unix()), redRow.Id)
	utils.CheckErr(write, err5, 105, "insertRedPacket:更新红包错误2")
	if err5 != nil {
		return
	}

	// 返回信息
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func drawRedPacket(write http.ResponseWriter, request *http.Request) {

	utils.Info("drawRedPacket check")

	// 获取参数
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "drawRedPacket:没有收到数据")
	if err != nil {
		return
	}

	var drawRedPacketD drawRedPacketData
	err1 := json.Unmarshal(body, &drawRedPacketD)

	utils.CheckErr(write, err1, 101, "drawRedPacket:无法解析json数据")
	if err1 != nil {
		return
	}

	// openId获取unionId
	unionId, err2 := model.UnionIdByUniqueId(drawRedPacketD.OpenId)
	utils.CheckErr(write, err2, 102, "drawRedPacket:无法获取用户信息")
	if err2 != nil {
		return
	}

	if unionId == "" {
		utils.CheckErr(write, errors.New("unionId获取失败, 请重新授权"), 110, "请点击开始游戏同意授权")
		return
	}

	// 请求php提现
	resp, err4 := http.Get("http://gc-api.ledongtian.com/gamecenter/public/api/drawGameActWG?openId=" + drawRedPacketD.OpenId + "&unionId=" + unionId + "&gameid=1")
	utils.CheckErr(write, err4, 104, "drawRedPacket:无法获取接口信息")
	if err4 != nil {
		return
	}

	defer resp.Body.Close()
	body, err5 := ioutil.ReadAll(resp.Body)
	utils.CheckErr(write, err5, 105, "drawRedPacket:无法获取接口data信息")
	if err5 != nil {
		return
	}

	response := drawRedPacketResponse{}
	err6 := json.Unmarshal(body, &response)
	utils.CheckErr(write, err6, 106, "drawRedPacket:无法解析body信息")
	if err6 != nil {
		return
	}

	// 判断是否提现成功
	if response.Code != 0 {
		utils.CheckErr(write, errors.New(response.Msg), 110, response.Msg)
		return
	} else {
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  response.Msg,
		}
		returnDa.Returnfunc(write)
	}
}

func getUserInfo(write http.ResponseWriter, request *http.Request) {

	utils.Info("getUserInfo check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "getUserInfo:没有收到更新的数据")
	if err != nil {
		return
	}

	updateD := videoD{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "getUserInfo:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	userInfo, err2 := model.UserByUniqueId(updateD.OpenId)
	utils.CheckErr(write, err2, 102, "getUserInfo:获取用户信息失败")
	if err2 != nil {
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"name":    UnicodeEmojiDecode(userInfo.Name),
			"headImg": userInfo.HeadImg,
		},
	}
	returnDa.Returnfunc(write)
}

func signin(write http.ResponseWriter, request *http.Request) {

	utils.Info("signin check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "signin:没有收到更新的数据")
	if err != nil {
		return
	}

	updateD := signinD{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "signin:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	w := md5.New()
	io.WriteString(w, updateD.OpenId+strconv.Itoa(updateD.Time)+utils.Config.Key)
	newSign := fmt.Sprintf("%x", w.Sum(nil))
	if newSign != updateD.Sign {
		utils.Info(updateD, newSign)
		utils.CheckErr(write, errors.New("密钥认证失败"), 122, "signin:密钥认证失败")
		return
	}

	userInfo, err2 := model.UserByUniqueId(updateD.OpenId)
	utils.CheckErr(write, err2, 102, "signin:获取用户信息失败")
	if err2 != nil {
		return
	}
	var now int = getNow()

	if userInfo.Signtime == now {
		utils.CheckErr(write, errors.New("今日已签到"), 103, "signin:今日已签到")
		return
	}

	_ = userInfo.Update("signtime", strconv.Itoa(now))
	_ = userInfo.Update("gem", strconv.Itoa(userInfo.Gem+200))

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func signinNew(write http.ResponseWriter, request *http.Request) {

	utils.Info("signinNew check")

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "signinNew:没有收到更新的数据")
	if err != nil {
		return
	}

	updateD := signinD{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "signinNew:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	if updateD.Iscoin == 0 {
		w := md5.New()
		io.WriteString(w, updateD.OpenId+strconv.Itoa(updateD.Gem)+strconv.Itoa(updateD.Time)+utils.Config.Key)
		newSign := fmt.Sprintf("%x", w.Sum(nil))
		if newSign != updateD.Sign {
			utils.Info(updateD, newSign)
			utils.CheckErr(write, errors.New("密钥认证失败"), 122, "signinNew:密钥认证失败")
			return
		}
	} else if updateD.Iscoin == 1 {
		w := md5.New()
		io.WriteString(w, updateD.OpenId+strconv.Itoa(updateD.Gem)+strconv.Itoa(updateD.Iscoin)+strconv.Itoa(updateD.Time)+utils.Config.Key)
		newSign := fmt.Sprintf("%x", w.Sum(nil))
		if newSign != updateD.Sign {
			utils.Info(updateD, newSign)
			utils.CheckErr(write, errors.New("密钥认证失败"), 122, "signinNew:密钥认证失败")
			return
		}
	}

	userInfo, err2 := model.UserByUniqueId(updateD.OpenId)
	utils.CheckErr(write, err2, 102, "signinNew:获取用户信息失败")
	if err2 != nil {
		return
	}
	var now = getNow()

	if userInfo.Signtime == now {
		utils.CheckErr(write, errors.New("今日已签到"), 103, "signinNew:今日已签到")
		return
	}

	_ = userInfo.Update("signtime", strconv.Itoa(now))
	if updateD.Iscoin == 1 {
		_ = userInfo.Update("coin", strconv.Itoa(updateD.Gem))
	} else {
		_ = userInfo.Update("gem", strconv.Itoa(updateD.Gem))
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func randPlayer(write http.ResponseWriter, request *http.Request) {

	utils.Info("randPlayer check")

	var nickName, headImg string
	err0 := model.Db.QueryRow("SELECT name, head_img FROM `users` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `users`)-(SELECT MIN(id) FROM `users`))+(SELECT MIN(id) FROM `users`)) AS id) AS t2 WHERE t1.id >= t2.id AND name != '' AND head_img != '' ORDER BY t1.id LIMIT 1").Scan(&nickName, &headImg)
	utils.CheckErr(write, err0, 100, "randPlayer:没有有效数据")

	// err0 := model.Db.QueryRow("SELECT name, head_img FROM `users`  WHERE id = ?", 410173).Scan(&nickName, &headImg)

	if err0 != nil {
		return
	}

	if nickName == "" {
		nickName = "玩家"
	}
	if headImg == "" {
		headImg = "http://h5static.ledongtian.com/games/wegameresource/mahjong/noname.png"
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"nickName": nickName,
			"headImg":  headImg,
		},
	}
	returnDa.Returnfunc(write)
}

func generalInviteList(write http.ResponseWriter, request *http.Request) {
	utils.Info("generalInviteList check")
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "generalInviteList:没有收到解密的数据")
	if err != nil {
		return
	}
	inviteD := Rank{}
	err1 := json.Unmarshal(body, &inviteD)
	utils.CheckErr(write, err1, 101, "generalInviteList:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	var inviteServer = model.NewInviteGemServer()

	// 获取邀请数据
	inviteTodayInfo, err2 := inviteServer.GetById(inviteD.OpenId)
	if err2 != nil { // 没有数据
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
			Data:    Map{},
		}
		returnDa.Returnfunc(write)
		return
	}

	var inviteList = make(map[int]Map)

	inviteArr := strings.Split(inviteTodayInfo.Invite, ",")
	isGetArr := strings.Split(inviteTodayInfo.IsGet, ",")

	for k, v := range inviteArr {
		id, _ := strconv.Atoi(v)
		userInfo, err3 := model.UserById(id)
		if err3 != nil {
			utils.CheckErr(write, err3, 103, "generalInviteList:获取用户信息失败")
		}
		isGet, _ := strconv.Atoi(isGetArr[k])

		inviteList[k] = Map{
			"id":     k,
			"isGet":  isGet,
			"avatar": userInfo.HeadImg,
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data:    inviteList,
	}
	returnDa.Returnfunc(write)
}

func generalInviteGet(write http.ResponseWriter, request *http.Request) {
	utils.Info("generalInviteGet check")
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "generalInviteGet:没有收到解密的数据")
	if err != nil {
		return
	}
	inviteD := model.PowerGet{}
	err1 := json.Unmarshal(body, &inviteD)
	utils.CheckErr(write, err1, 101, "generalInviteGet:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	var inviteServer = model.NewInviteGemServer()

	// 获取邀请数据
	inviteTodayInfo, err2 := inviteServer.GetById(inviteD.OpenId)
	utils.CheckErr(write, err2, 102, "generalInviteGet:邀请记录不存在")
	if err2 != nil {
		return
	}

	isGetArr := strings.Split(inviteTodayInfo.IsGet, ",")

	// 检测是否已被领取
	if isGetArr[inviteD.Id] == "1" {
		utils.CheckErr(write, errors.New("钞票已领取"), 103, "generalInviteGet:钞票已领取")
		return
	}

	userInfo, err4 := model.UserByUniqueId(inviteD.OpenId)
	utils.CheckErr(write, err4, 104, "generalInviteGet:获取用户信息失败")
	if err4 != nil {
		return
	}

	// 设置已领取
	isGetArr[inviteD.Id] = "1"

	// 添加钞票
	var count = 200
	err5 := userInfo.Update("gem", strconv.Itoa(userInfo.Gem+count))
	utils.CheckErr(write, err5, 105, "generalInviteGet:添加钞票失败")
	if err5 != nil {
		return
	}

	// 更新领取记录标识
	inviteTodayInfo.IsGet = strings.Replace(strings.Trim(fmt.Sprint(isGetArr), "[]"), " ", ",", -1)
	err6 := inviteServer.UpdateInvite(inviteTodayInfo)
	utils.CheckErr(write, err6, 106, "generalInviteGet:更新领取标识失败")
	if err6 != nil {
		return
	}

	// 返回最新钞票
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"gem":    200,
			"gemAll": userInfo.Gem + count,
		},
	}
	returnDa.Returnfunc(write)
}

*/

func newVideo(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "newVideo:没有收到更新的数据")
	if err != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	updateD := VideoAppData{}
	err1 := json.Unmarshal(body, &updateD)
	utils.CheckErr(write, err1, 101, "newVideo:无法解析更新的json数据")
	if err1 != nil {
		return
	}
	// utils.Info(updateD)
	// 更新redis incr diff_video_app_ 1:游戏结束 2:格子 3:查找 4:上一步 5:炸弹 6:天降金币 7:过关红包 8:食材盒子 9:开宝箱
	if updateD.Types > 0 && updateD.Types <= 10 {
		s := strconv.Itoa(getNow())
		videoType := strconv.Itoa(updateD.Types)
		key := utils.Config.PkgName + "_video_new_" + videoType
		keyDay := utils.Config.PkgName + "_video_new_" + videoType + "_" + s

		_, resErr := rc.Do("INCR", key)
		utils.CheckErr(write, resErr, 102, "newVideo:更新type redis失败")
		if resErr != nil {
			return
		}
		_, err3 := rc.Do("INCR", keyDay)
		utils.CheckErr(write, resErr, 103, "newVideo:更新typeDay redis失败")
		if err3 != nil {
			return
		}

		if updateD.Channel != "" {
			channel := updateD.Channel
			keyChannel := utils.Config.PkgName + "_video_new_" + channel + "_" + videoType
			keyDayChannel := utils.Config.PkgName + "_video_new_" + channel + "_" + videoType + "_" + s

			_, resErr := rc.Do("INCR", keyChannel)
			utils.CheckErr(write, resErr, 104, "newVideo:更新keyChannel redis失败")
			if resErr != nil {
				return
			}
			_, err3 := rc.Do("INCR", keyDayChannel)
			utils.CheckErr(write, resErr, 105, "newVideo:更新keyDayChannel redis失败")
			if err3 != nil {
				return
			}
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func levelPeopleN(write http.ResponseWriter, request *http.Request) {
	s := getNow() - 24*60*60*1
	key := utils.Config.PkgName + "_level_day_" + strconv.Itoa(s)
	// utils.Info(key)
	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	newList := make(map[int]int)
	newList2 := make(map[int]float64)

	for i := 1; i <= 500; i++ {
		level, err := redis.Int(rc.Do("ZSCORE", key, i))

		if err != nil {
			newList[i] = 0
		} else {
			newList[i] = level
		}
	}

	for k, v := range newList {
		if k == 1 {
			count := model.GetCount(s, s+23*60*60+59*60+59)
			newList2[k] = Decimal(float64(v) / float64(count))
		} else if v == 0 || newList[k-1] == 0 {
			continue
		} else {
			newList2[k] = Decimal(float64(v) / float64(newList[k-1]))
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"level": newList,
			"rate":  newList2,
		},
	}
	returnDa.Returnfunc(write)
}

func Decimal(value float64) float64 {
	value, err := strconv.ParseFloat(fmt.Sprintf("%.5f", value), 64)
	if err != nil {
		utils.Info("decimal error: ", err)
	}
	return value
}

func levelPeopleToday(write http.ResponseWriter, request *http.Request) {
	s := getNow()
	key := utils.Config.PkgName + "_level_day_" + strconv.Itoa(s)
	// utils.Info(key)
	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	newList := make(map[int]int)
	newList2 := make(map[int]float64)

	for i := 1; i <= 500; i++ {
		level, err := redis.Int(rc.Do("ZSCORE", key, i))
		if err != nil {
			newList[i] = 0
		} else {
			newList[i] = level
		}
	}

	for k, v := range newList {
		if k == 1 {
			count := model.GetCount(s, s+23*60*60+59*60+59)
			newList2[k] = Decimal(float64(v) / float64(count))
		} else if v == 0 || newList[k-1] == 0 {
			continue
		} else {
			newList2[k] = Decimal(float64(v) / float64(newList[k-1]))
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"level": newList,
			"rate":  newList2,
		},
	}
	returnDa.Returnfunc(write)
}

func friends(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "friends:没有收到更新的数据")
	if err != nil {
		return
	}

	data := model.Friend{}
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "friends:无法解析更新的json数据")
	if err1 != nil {
		return
	}

	var infos []model.FriendsList

	inviteServer := model.NewInviteServer()
	info := inviteServer.GetInvited(data.UniqueId)
	if info != nil {
		for _, friendInfo := range info {
			name := ""
			if friendInfo.Name == "" {
				name = "未授权"
			} else {
				name = UnicodeEmojiDecode(friendInfo.Name)
			}

			avatar := ""
			if friendInfo.Avatar == "" {
				avatar = "http://h5static.ledongtian.com/games/wegameresource/mahjong/noname.png"
			} else {
				avatar = friendInfo.Avatar
			}

			infos = append(infos, model.FriendsList{
				Name:    name,
				Avatar:  avatar,
				Balance: friendInfo.Balance,
			})
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"friends": infos,
		},
	}
	returnDa.Returnfunc(write)
}

func invite(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "invite:没有收到解密的数据")
	if err != nil {
		return
	}
	friendD := model.GeneralInvite{}
	err1 := json.Unmarshal(body, &friendD)
	utils.CheckErr(write, err1, 101, "invite:无法解析解密的json数据")
	if err1 != nil {
		return
	}
	// utils.Info(friendD)
	if friendD.ShareCode == "" || friendD.OpenId == "" {
		utils.CheckErr(write, errors.New("输入参数不能为空"), 102, "invite:输入参数不能为空")
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	if friendD.ShareId > 0 {
		s := strconv.Itoa(getNow())
		shareId := strconv.Itoa(friendD.ShareId)
		key := utils.Config.PkgName + "_share_new_" + shareId
		keyDay := utils.Config.PkgName + "_share_new_" + shareId + "_" + s

		_, err7 := rc.Do("INCR", key)
		utils.CheckErr(write, err7, 107, "invite:更新type redis失败")
		if err7 != nil {
			return
		}
		_, err8 := rc.Do("INCR", keyDay)
		utils.CheckErr(write, err8, 108, "invite:更新typeDay redis失败")
		if err8 != nil {
			return
		}
	}

	// 根据user_shareCode查询宿主userId
	rootUserId, err3 := redis.Int(rc.Do("HGET", utils.Config.PkgName+"-shareCode_list", friendD.ShareCode))
	utils.CheckErr(write, err3, 103, "invite:查询shareCode用户id失败")
	if err3 != nil {
		return
	}

	openId, err4 := model.OpenIdByUserId(rootUserId)
	utils.CheckErr(write, err4, 104, "invite:获取用户信息失败")
	if err4 != nil {
		return
	}

	if openId == friendD.OpenId {
		utils.CheckErr(write, errors.New("自己不能邀请自己"), 105, "invite:自己不能邀请自己")
		return
	}

	// 获取好友用户信息
	friendInfo, err6 := model.UserByUniqueId(friendD.OpenId)
	utils.CheckErr(write, err6, 106, "invite:获取好友用户信息失败")
	if err6 != nil {
		return
	}

	// 判断是否为新玩家
	var (
		now = int(time.Now().Unix())
	)

	if (now - friendInfo.Time) > 1 { // 老用户
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
		}
		returnDa.Returnfunc(write)
		return
	}

	inviteServer := model.NewInviteServer()

	// 查询被邀请人是否已经被邀请
	if inviteServer.Invited(friendD.OpenId) > 0 {
		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
		}
		returnDa.Returnfunc(write)
		return
	}

	inviteInfo := model.InviteList{
		OpenId:       openId,
		InviteOpenId: friendD.OpenId,
		Time:         now,
	}

	err = inviteServer.Create(&inviteInfo)
	// 如果有错误记录
	if err != nil {
		utils.Error(err)
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func inviteData(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "inviteData:没有收到解密的数据")
	if err != nil {
		return
	}
	friendD := model.InviteData{}
	err1 := json.Unmarshal(body, &friendD)
	utils.CheckErr(write, err1, 101, "inviteData:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	if friendD.OpenId == "" {
		utils.CheckErr(write, errors.New("输入参数不能为空"), 102, "inviteData:输入参数不能为空")
		return
	}

	inviteServer := model.NewInviteServer()

	// 查询被邀请人是否已经被邀请
	var getRow []string
	var imgRow []string

	count := inviteServer.InviteCount(friendD.OpenId)
	if count > 0 {
		user, err := model.InviteUniqueId(friendD.OpenId)
		if err != nil {
			utils.Error("inviteData:获取用户信息失败")
		} else if user.InviteGet != "" {
			getRow = strings.Split(user.InviteGet, ",")
		}

		// 获取邀请人的头像
		info := inviteServer.GetInvited2(friendD.OpenId)
		if info != nil {
			for _, friendInfo := range info {
				avatar := ""
				if friendInfo.Avatar == "" {
					avatar = "http://h5static.ledongtian.com/games/wegameresource/mahjong/noname.png"
				} else {
					avatar = friendInfo.Avatar
				}

				imgRow = append(imgRow, avatar)
			}
		}
	}

	if friendD.Click == 1 {
		// 从池里获取连接
		rc := model.RedisClient.Get()
		// 用完后将连接放回连接池
		defer rc.Close()

		s := strconv.Itoa(getNow())
		keyDay := utils.Config.PkgName + "_share_click_" + s
		_, resErr := rc.Do("INCR", keyDay)
		if resErr != nil {
			utils.Error("inviteData:更新 share_click redis失败")
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"count":  count,
			"getRow": getRow,
			"imgRow": imgRow,
		},
	}
	returnDa.Returnfunc(write)
}

/*
提现好友红包
1.是否满足提现条件, 邀请1,5,10,20,30,50,100
*/
func withdraw(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "withdraw:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.WithDraw1
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "withdraw:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	key := utils.Config.PkgName + "_ttl_withdraw_" + data.OpenId
	_, err100 := redis.Int(rc.Do("get", key))
	if err100 == nil { // 查到了，证明为连续请求，处理
		utils.CheckErr(write, errors.New("重复请求"), 101, "withdraw:重复请求")
		return
	} else { // 没查到，第一次请求，放行并设置key
		_, _ = rc.Do("setex", key, 7, 0)
	}

	drawServer := model.NewDrawServer()

	// 1. 判断平台今日可提现金额是否超过1000元
	sum, _ := drawServer.GetSumAllTime(getNow())
	if sum >= 100000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 104, "withdraw:今日提现额度已达上限")
		return
	}

	// 2. 判断用户今日可提现金额是否超过30元
	sum, _ = drawServer.GetSumDayTime(data.OpenId, getNow())
	if sum >= 3000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 105, "withdraw:今日提现额度已达上限")
		return
	}

	// 3. 判断用户是否满足领取条件
	drawRow := []int{1, 5, 10, 20, 30, 50, 100}
	drawFlag := 0
	for _, x := range drawRow {
		if data.Types == x {
			drawFlag = 1
			break
		}
	}

	if drawFlag != 1 || data.Types == 100 {
		utils.CheckErr(write, errors.New("领取条件错误"), 106, "withdraw:领取条件错误")
		return
	}

	// 判断是否邀请了相应数量的好友
	inviteServer := model.NewInviteServer()
	count := inviteServer.InviteCount20(data.OpenId)
	if data.Types > count {
		utils.CheckErr(write, errors.New("未达到领取条件"), 107, "withdraw:未达到领取条件")
		return
	}

	// 4. 判断是否领取过
	user, err := model.InviteUniqueId(data.OpenId)
	if err != nil {
		utils.CheckErr(write, errors.New("获取用户信息失败"), 108, "withdraw:获取用户信息失败")
		return
	}

	var row []string
	if user.InviteGet != "" {
		row = strings.Split(user.InviteGet, ",")
		for _, tmp := range row {
			l, _ := strconv.Atoi(tmp)
			if l == data.Types {
				utils.CheckErr(write, errors.New("该奖励已经领取"), 109, "withdraw:该奖励已经领取")
				return
			}
		}
	}

	money := 0
	// 根据type判断是否符合连续签到时长,以及是否领取过
	switch data.Types {
	case 1:
		money = 30
	case 5:
		money = 100
	case 10:
		money = 150
	case 20:
		money = 300
	case 30:
		money = 300
	case 50:
		money = 500
	case 100:
		money = 10000
	}

	createTime := getTime()
	w := md5.New()
	_, _ = io.WriteString(w, data.OpenId+strconv.Itoa(createTime)+strconv.Itoa(money))
	sign := fmt.Sprintf("%x", w.Sum(nil))

	// 生成提现记录
	drawInfo := &model.DrawList{
		OpenId:     data.OpenId,
		Money:      money,
		CreateTime: createTime,
		CreatedDay: getNow(),
		Sign:       sign,
		Name:       data.Types,
	}
	err = drawServer.Create(drawInfo)
	if err != nil {
		utils.CheckErr(write, err, 111, "withdraw:生成提现记录失败")
		return
	}

	// 提前修改领取记录
	/*row = append(row, strconv.Itoa(data.Types))
	str := arr2Str(row)
	err77 := user.Update("invite_get", str)
	utils.CheckErr(write, err, 112, "withdraw:更新领取记录失败")
	if err77 != nil {
		return
	}*/

	// 5. 关联检测
	unionOpenId, codeNo := checkUnion(data.OpenId)
	if codeNo > 0 {
		utils.CheckErr(write, err, 113, "withdraw:系统异常,请重试")
		return
	}
	// 6. 如果已关联,直接调用block接口 提现
	if unionOpenId != "" {
		code, err := drawMahjongFunc(unionOpenId, sign, 0)
		// 判断是否提现成功
		if code != 0 {
			utils.CheckErr(write, err, 110, "提现失败")
			return
		} else {
			returnDa := utils.ReturnData{
				Errcode: 0,
				Errmsg:  "提现成功,请查看微信支付消息!",
			}
			returnDa.Returnfunc(write)
		}
	} else { // 7. 如果未关联,告知并返回前端openid+sign并跳转到block新接口
		returnDa := utils.ReturnData{
			Errcode: 1000,
			Errmsg:  "",
			Data: Map{
				"open_id": data.OpenId,
				"sign":    sign,
			},
		}
		returnDa.Returnfunc(write)
	}
}

/*
提现好友红包
1.是否满足提现条件, 邀请1,3,5,7,9,10
*/
func withdraw2(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "withdraw2:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.WithDraw1
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "withdraw2:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	key := utils.Config.PkgName + "_ttl_withdraw_" + data.OpenId
	_, err100 := redis.Int(rc.Do("get", key))
	if err100 == nil { // 查到了，证明为连续请求，处理
		utils.CheckErr(write, errors.New("重复请求"), 101, "withdraw2:重复请求")
		return
	} else { // 没查到，第一次请求，放行并设置key
		_, _ = rc.Do("setex", key, 7, 0)
	}

	drawServer := model.NewDrawServer()

	// 1. 判断平台今日可提现金额是否超过1000元
	sum, _ := drawServer.GetSumAllTime(getNow())
	if sum >= 100000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 104, "withdraw2:今日提现额度已达上限")
		return
	}

	// 2. 判断用户今日可提现金额是否超过30元
	sum, _ = drawServer.GetSumDayTime(data.OpenId, getNow())
	if sum >= 3000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 105, "withdraw2:今日提现额度已达上限")
		return
	}

	// 3. 判断用户是否满足领取条件
	drawFlag := 0
	if data.Types >= 1 && data.Types <= 10 {
		drawFlag = 1
	}

	if drawFlag != 1 {
		utils.CheckErr(write, errors.New("领取条件错误"), 106, "withdraw2:领取条件错误")
		return
	}

	// 判断是否邀请了相应数量的好友
	inviteServer := model.NewInviteServer()
	count := inviteServer.InviteCount20(data.OpenId)
	if data.Types > count {
		utils.CheckErr(write, errors.New("未达到领取条件"), 107, "withdraw2:未达到领取条件")
		return
	}

	// 4. 判断是否领取过
	user, err := model.InviteUniqueId(data.OpenId)
	if err != nil {
		utils.CheckErr(write, errors.New("获取用户信息失败"), 108, "withdraw2:获取用户信息失败")
		return
	}

	var row []string
	if user.InviteGet != "" {
		row = strings.Split(user.InviteGet, ",")
		for _, tmp := range row {
			l, _ := strconv.Atoi(tmp)
			if l == data.Types {
				utils.CheckErr(write, errors.New("该奖励已经领取"), 109, "withdraw2:该奖励已经领取")
				return
			}
		}
	}

	// 判断如果用户领取道具,直接记录
	if data.Types == 2 || data.Types == 4 || data.Types == 6 || data.Types == 8 {
		row = append(row, strconv.Itoa(data.Types))
		str := arr2Str(row)
		err77 := user.Update("invite_get", str)
		utils.CheckErr(write, err, 112, "withdraw2:更新领取记录失败")
		if err77 != nil {
			return
		}

		returnDa := utils.ReturnData{
			Errcode: 2000,
			Errmsg:  "道具领取成功!",
		}
		returnDa.Returnfunc(write)
		return
	}

	money := 0
	// 根据type判断是否符合连续签到时长,以及是否领取过
	switch data.Types {
	case 1:
		money = 50
	case 3:
		money = 100
	case 5:
		money = 200
	case 7:
		money = 300
	case 9:
		money = 500
	case 10:
		money = 500
	}

	createTime := getTime()
	w := md5.New()
	_, _ = io.WriteString(w, data.OpenId+strconv.Itoa(createTime)+strconv.Itoa(money))
	sign := fmt.Sprintf("%x", w.Sum(nil))

	// 生成提现记录
	drawInfo := &model.DrawList{
		OpenId:     data.OpenId,
		Money:      money,
		CreateTime: createTime,
		CreatedDay: getNow(),
		Sign:       sign,
		Name:       data.Types,
	}
	err = drawServer.Create(drawInfo)
	if err != nil {
		utils.CheckErr(write, err, 111, "withdraw2:生成提现记录失败")
		return
	}

	// 提前修改领取记录
	/*row = append(row, strconv.Itoa(data.Types))
	str := arr2Str(row)
	err77 := user.Update("invite_get", str)
	utils.CheckErr(write, err, 112, "withdraw:更新领取记录失败")
	if err77 != nil {
		return
	}*/

	// 5. 关联检测
	unionOpenId, codeNo := checkUnion(data.OpenId)
	if codeNo > 0 {
		utils.CheckErr(write, err, 113, "withdraw2:系统异常,请重试")
		return
	}
	// 6. 如果已关联,直接调用block接口 提现
	if unionOpenId != "" {
		code, err := drawMahjongFunc(unionOpenId, sign, 0)
		// 判断是否提现成功
		if code != 0 {
			utils.CheckErr(write, err, 110, "提现失败")
			return
		} else {
			returnDa := utils.ReturnData{
				Errcode: 0,
				Errmsg:  "提现成功,请查看微信支付消息!",
			}
			returnDa.Returnfunc(write)
		}
	} else { // 7. 如果未关联,告知并返回前端openid+sign并跳转到block新接口
		returnDa := utils.ReturnData{
			Errcode: 1000,
			Errmsg:  "",
			Data: Map{
				"open_id": data.OpenId,
				"sign":    sign,
			},
		}
		returnDa.Returnfunc(write)
	}
}

/*
提现好友红包
1.是否满足提现条件, 邀请1,3,5,7,10
*/
func withdraw3(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "withdraw3:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.WithDraw1
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "withdraw3:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	key := utils.Config.PkgName + "_ttl_withdraw_" + data.OpenId
	_, err100 := redis.Int(rc.Do("get", key))
	if err100 == nil { // 查到了，证明为连续请求，处理
		utils.CheckErr(write, errors.New("重复请求"), 101, "重复请求")
		return
	} else { // 没查到，第一次请求，放行并设置key
		_, _ = rc.Do("setex", key, 7, 0)
	}

	drawServer := model.NewDrawServer()

	// 1. 判断平台今日可提现金额是否超过1000元
	sum, _ := drawServer.GetSumAllTime(getNow())
	if sum >= 100000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 104, "withdraw3:今日提现额度已达上限")
		return
	}

	// 2. 判断用户今日可提现金额是否超过30元
	sum, _ = drawServer.GetSumDayTime(data.OpenId, getNow())
	if sum >= 3000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 105, "withdraw3:今日提现额度已达上限")
		return
	}

	// 3. 判断用户是否满足领取条件
	drawFlag := 0
	if data.Types >= 1 && data.Types <= 10 {
		drawFlag = 1
	}

	if drawFlag != 1 {
		utils.CheckErr(write, errors.New("领取条件错误"), 106, "withdraw3:领取条件错误")
		return
	}

	// 判断是否邀请了相应数量的好友
	inviteServer := model.NewInviteServer()
	count := inviteServer.InviteCount20(data.OpenId)
	if data.Types > count {
		utils.CheckErr(write, errors.New("未达到领取条件"), 107, "未达到领取条件")
		return
	}

	// 4. 判断是否领取过
	user, err := model.InviteUniqueId(data.OpenId)
	if err != nil {
		utils.CheckErr(write, errors.New("获取用户信息失败"), 108, "withdraw3:获取用户信息失败")
		return
	}

	var row []string
	if user.InviteGet != "" {
		row = strings.Split(user.InviteGet, ",")
		for _, tmp := range row {
			l, _ := strconv.Atoi(tmp)
			if l == data.Types {
				utils.CheckErr(write, errors.New("该奖励已经领取"), 109, "withdraw3:该奖励已经领取")
				return
			}
		}
	}

	// 判断如果用户领取道具,直接记录
	if data.Types == 2 || data.Types == 4 || data.Types == 6 || data.Types == 8 || data.Types == 9 {
		row = append(row, strconv.Itoa(data.Types))
		str := arr2Str(row)
		err77 := user.Update("invite_get", str)
		utils.CheckErr(write, err, 112, "withdraw3:更新领取记录失败")
		if err77 != nil {
			return
		}

		returnDa := utils.ReturnData{
			Errcode: 2000,
			Errmsg:  "道具领取成功!",
		}
		returnDa.Returnfunc(write)
		return
	}

	money := 0
	// 根据type判断是否符合连续签到时长,以及是否领取过
	switch data.Types {
	case 1:
		money = 30
	case 3:
		money = 50
	case 5:
		money = 100
	case 7:
		money = 100
	case 10:
		money = 200
	}

	createTime := getTime()
	w := md5.New()
	_, _ = io.WriteString(w, data.OpenId+strconv.Itoa(createTime)+strconv.Itoa(money))
	sign := fmt.Sprintf("%x", w.Sum(nil))

	// 生成提现记录
	drawInfo := &model.DrawList{
		OpenId:     data.OpenId,
		Money:      money,
		CreateTime: createTime,
		CreatedDay: getNow(),
		Sign:       sign,
		Name:       data.Types,
	}
	err = drawServer.Create(drawInfo)
	if err != nil {
		utils.CheckErr(write, err, 111, "withdraw3:生成提现记录失败")
		return
	}

	// 提前修改领取记录
	/*row = append(row, strconv.Itoa(data.Types))
	str := arr2Str(row)
	err77 := user.Update("invite_get", str)
	utils.CheckErr(write, err, 112, "withdraw:更新领取记录失败")
	if err77 != nil {
		return
	}*/

	// 5. 关联检测
	unionOpenId, codeNo := checkUnion(data.OpenId)
	if codeNo > 0 {
		utils.CheckErr(write, err, 113, "withdraw3:系统异常,请重试")
		return
	}
	// 6. 如果已关联,直接调用block接口 提现
	if unionOpenId != "" {
		code, err := drawMahjongFunc(unionOpenId, sign, 0)
		// 判断是否提现成功
		if code != 0 {
			utils.CheckErr(write, err, 110, "提现失败")
			return
		} else {
			returnDa := utils.ReturnData{
				Errcode: 0,
				Errmsg:  "提现成功,请查看微信支付消息!",
			}
			returnDa.Returnfunc(write)
		}
	} else { // 7. 如果未关联,告知并返回前端openid+sign并跳转到block新接口
		returnDa := utils.ReturnData{
			Errcode: 1000,
			Errmsg:  "",
			Data: Map{
				"open_id": data.OpenId,
				"sign":    sign,
			},
		}
		returnDa.Returnfunc(write)
	}
}

func qrcode(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "qrcode:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.InviteData
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "qrcode:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	user, err := model.InviteUniqueId(data.OpenId)
	utils.CheckErr(write, err, 102, "qrcode:获取用户信息失败")
	if err != nil {
		return
	}

	// 获取shareCode
	w := md5.New()
	io.WriteString(w, user.UniqueId+strconv.Itoa(user.Id))
	shareCode := fmt.Sprintf("%x", w.Sum(nil))
	// utils.Info(shareCode)
	tmp := model.Qrcode{Scene: shareCode, Width: 128}
	png, err := post(tmp)
	utils.CheckErr(write, err, 103, "qrcode:获取小程序码失败")
	if err != nil {
		return
	}

	// 返回
	write.Header().Set("Access-Control-Allow-Origin", "*") // 允许访问所有域
	write.Header().Set("Access-Control-Allow-Credentials", "true")
	write.Header().Add("Access-Control-Allow-Headers", "Content-Type") // header的类型
	write.Header().Set("content-type", "application/octet-stream")

	tmp1 := base64.StdEncoding.EncodeToString(png)
	write.Write([]byte(tmp1))
}

func reward(write http.ResponseWriter, request *http.Request) {

	var nickName string

	_ = model.Db.QueryRow("SELECT name FROM `rewards` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `rewards`)-(SELECT MIN(id) FROM `rewards`))+(SELECT MIN(id) FROM `rewards`)) AS id) AS t2 WHERE t1.id >= t2.id AND name != '' ORDER BY t1.id LIMIT 1").Scan(&nickName)

	if nickName == "" {
		names := []string{"喵了个汪[\u1f436]", "姜博", "追风筝的人", "蓝莓小蛋糕", "高淑琴", "biu～", "MEI", "A威特斯洗衣小丽", "[\u1f337]唯一的你[\u1f490]", "小红帽"}
		nickName = names[rand.Intn(10)]
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"name": nickName,
		},
	}
	returnDa.Returnfunc(write)
}

func downRedis(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "downRedis:没有收到解密的数据")
	if err != nil {
		return
	}
	rankD := DownRedis{}
	err1 := json.Unmarshal(body, &rankD)
	utils.CheckErr(write, err1, 101, "downRedis:无法解析解密的json数据")
	if err1 != nil {
		return
	}

	if rankD.Start >= 0 && rankD.End > 0 && rankD.Start < rankD.End {

		// 从池里获取连接
		rc := model.RedisClient.Get()
		// 用完后将连接放回连接池
		defer rc.Close()

		// list	redis.zrevrange(game + 'rank', 0, 19, "withscores")获取前二十名用户 倒叙
		rankList, err3 := redis.Strings(rc.Do("zrevrange", utils.Config.PkgName+"_rank", rankD.Start, rankD.End))
		utils.CheckErr(write, err3, 103, "downRedis:获取排行榜失败")
		if err3 != nil {
			return
		}

		/*for i := 0; i < len(rankList); i += 2 {
			// 查找用户

			userInfo1, err5 := model.UserByUniqueId(rankList[i])
			utils.CheckErr(write, err5, 105, "rank:获取用户信息失败")
			if err5 != nil {
				return
			}
			temp, _ := strconv.Atoi(rankList[i+1])

			if userInfo1.Name == "" {
				userName = "游戏玩家"
			} else {
				userName = UnicodeEmojiDecode(userInfo1.Name)
			}

			if userInfo1.HeadImg == "" {
				headImg = "http://h5static.ledongtian.com/games/wegameresource/mahjong/noname.png"
			} else {
				headImg = userInfo1.HeadImg
			}

			newList[j] = Map{
				"name":    userName,
				"headImg": headImg,
				"score":   temp,
				"rank":    int(math.Floor(float64(i/2)) + 1),
			}
			j++
		}*/

		returnDa := utils.ReturnData{
			Errcode: 0,
			Errmsg:  "is ok",
			Data:    rankList,
		}
		returnDa.Returnfunc(write)
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

/*
更新食材, key = [], val = []
*/
func updateStock(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "updateStock:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.UpStock
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "updateStock:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	if len(data.Key) != len(data.Val) || len(data.Key) < 1 || data.OpenId == "" {
		utils.CheckErr(write, errors.New("参数错误"), 102, "updateStock:参数错误")
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	// 保存某一关是否获取食材盒子以确保一关仅能获得一个
	if data.Level > 0 {

		_, errx := rc.Do("SET", utils.Config.PkgName+"_foodLevel_"+data.OpenId, data.Level)
		if errx != nil {
			utils.Error("updateStock:update foodLevel error")
		}
	}

	if data.Types > 0 {
		s := strconv.Itoa(getNow())
		if data.Types == 1 { // 获得食材盒子
			keyDay := utils.Config.PkgName + "_stock_add_" + s
			_, resErr := rc.Do("INCR", keyDay)
			utils.CheckErr(write, resErr, 105, "updateStock:更新type add redis失败")
			if resErr != nil {
				return
			}
		} else if data.Types == 2 { // 获得食材盒子
			keyDay := utils.Config.PkgName + "_stock_use_" + s
			_, resErr := rc.Do("INCR", keyDay)
			utils.CheckErr(write, resErr, 105, "updateStock:更新type use redis失败")
			if resErr != nil {
				return
			}
		}
	}

	// 获取仓库数量
	foodServer := model.NewFoodServer()
	stockStr, err := foodServer.GetStock(data.OpenId)
	utils.CheckErr(write, err, 103, "updateStock:获取仓库数据失败")
	if err != nil {
		return
	}

	if stockStr != "" {
		stockArr := strings.Split(stockStr, ",")
		for key, val := range data.Key {
			stockArr[val] = strconv.Itoa(data.Val[key])
		}

		stockStr = strings.Replace(strings.Trim(fmt.Sprint(stockArr), "[]"), " ", ",", -1)
		err := foodServer.SetStock(data.OpenId, stockStr)
		utils.CheckErr(write, err, 104, "updateStock:更新数据失败")
		if err != nil {
			return
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)

}

/*
开启店铺
*/
func storeOpen(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "storeOpen:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.StoreOpen
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "storeOpen:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	if data.OpenId == "" {
		utils.CheckErr(write, errors.New("参数错误"), 102, "storeOpen:参数错误")
		return
	}

	// 获取仓库数量
	foodServer := model.NewFoodServer()

	err = foodServer.OpenStore(data.OpenId)
	utils.CheckErr(write, err, 103, "storeOpen:开启店铺失败")
	if err != nil {
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)

}

/*
店铺升级
*/
func storeLevelUp(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "storeLevelUp:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.StoreLevelUp
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "storeLevelUp:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	if data.OpenId == "" || data.Level < 1 {
		utils.CheckErr(write, errors.New("参数错误"), 102, "storeLevelUp:参数错误")
		return
	}

	// 获取仓库数量
	foodServer := model.NewFoodServer()

	err = foodServer.StoreLevelUp(data.OpenId, data.Level)
	utils.CheckErr(write, err, 103, "storeLevelUp:店铺升级失败")
	if err != nil {
		return
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)

}

/*
制作食物
1.completes
2.金币
3.食材数量
*/
func foodUp(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "foodUp:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.FoodUp
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "foodUp:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	if len(data.Key) != len(data.Val) || len(data.Key) < 1 || data.OpenId == "" || data.Coin < 0 || len(data.Completes) != 5 {
		utils.CheckErr(write, errors.New("参数错误"), 102, "foodUp:参数错误")
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	s := strconv.Itoa(getNow())
	// 统计制作食物次数
	keyDay := utils.Config.PkgName + "_food_up_" + s
	_, resErr := rc.Do("INCR", keyDay)
	utils.CheckErr(write, resErr, 107, "foodUp:更新type up redis失败")
	if resErr != nil {
		return
	}

	// 获取仓库数量
	foodServer := model.NewFoodServer()
	stockStr, err := foodServer.GetStock(data.OpenId)
	utils.CheckErr(write, err, 103, "foodUp:获取仓库数据失败")
	if err != nil {
		return
	}

	if stockStr != "" {
		// 更新仓库食材
		stockArr := strings.Split(stockStr, ",")
		for key, val := range data.Key {
			stockArr[val] = strconv.Itoa(data.Val[key])
		}

		stockStr = strings.Replace(strings.Trim(fmt.Sprint(stockArr), "[]"), " ", ",", -1)
		err := foodServer.SetStock(data.OpenId, stockStr)
		utils.CheckErr(write, err, 104, "foodUp:更新数据失败")
		if err != nil {
			return
		}

		// 更新完成度
		newCompletes := make([]int, 5)
		for key, val := range data.Completes {
			tmp := 0
			if val == true {
				tmp = 1
			}
			newCompletes[key] = tmp
		}
		// utils.Info(data.Completes, newCompletes)

		newCompletesStr := strings.Replace(strings.Trim(fmt.Sprint(newCompletes), "[]"), " ", ",", -1)
		err = foodServer.UpCompletes(data.OpenId, newCompletesStr)
		utils.CheckErr(write, err, 105, "foodUp:更新完成度失败")
		if err != nil {
			return
		}

		// 更新金币
		err = model.UpdateCoin(data.OpenId, data.Coin)
		utils.CheckErr(write, err, 106, "foodUp:更新金币失败")
		if err != nil {
			return
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)

}

/*
更新任务数据
types == 0 task_data | types == 1 task_level
*/
func task(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "task:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.Task
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "task:无法解析登录的json数据")
	if err1 != nil {
		return
	}
	// utils.Info(data)
	if data.OpenId == "" || data.Types < 0 || data.Types > 1 || len(data.Data) != 3 || data.Coin < 0 {
		utils.CheckErr(write, errors.New("参数错误"), 102, "task:参数错误")
		return
	}

	// 获取仓库数量
	foodServer := model.NewFoodServer()
	stockStr, err := foodServer.GetStock(data.OpenId)
	utils.CheckErr(write, err, 103, "task:获取仓库数据失败")
	if err != nil {
		return
	}

	if stockStr != "" {

		newData := strings.Replace(strings.Trim(fmt.Sprint(data.Data), "[]"), " ", ",", -1)
		// utils.Info(newData)
		if data.Types == 0 { // 更新task_data
			err = foodServer.TaskDataUp(data.OpenId, newData)
			utils.CheckErr(write, err, 104, "task:更新任务数据失败")
			if err != nil {
				return
			}
		} else { // 更新task_level
			err = foodServer.TaskLevelUp(data.OpenId, newData)
			utils.CheckErr(write, err, 104, "task:更新任务数据失败")
			if err != nil {
				return
			}

			// 更新金币
			if data.Coin > 0 {
				err = model.UpdateCoin(data.OpenId, data.Coin)
				utils.CheckErr(write, err, 105, "task:更新金币失败")
				if err != nil {
					return
				}
			}
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)

}

func subscribe(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "subscribe:没有收到登录数据")
	if err != nil {
		return
	}

	var upgradeD model.PUpgrade
	err1 := json.Unmarshal(body, &upgradeD)
	utils.CheckErr(write, err1, 101, "subscribe:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	if upgradeD.Time <= 0 {
		utils.CheckErr(write, errors.New("参数错误"), 104, "subscribe:参数错误")
		return
	}

	powerServer := model.NewLuckServer()
	if powerServer.GetCount(upgradeD.OpenId) == 1 {
		tmpTime := int(time.Now().Unix())
		power := model.Luck{
			OpenId:        upgradeD.OpenId,
			SendTime:      0,
			RemainTime:    upgradeD.Time,
			UpdateTime:    tmpTime,
			SubscribeTime: tmpTime,
		}

		err := powerServer.UpdateAll(power)

		if err != nil {
			utils.CheckErr(write, errors.New("更新失败"), 103, "subscribe:更新失败")
			return
		}
	} else {
		tmpTime := int(time.Now().Unix())
		power := &model.Luck{
			OpenId:        upgradeD.OpenId,
			RemainTime:    upgradeD.Time,
			UpdateTime:    tmpTime,
			SubscribeTime: tmpTime,
		}
		err := powerServer.Create(power)
		if err != nil {
			utils.CheckErr(write, errors.New("订阅失败"), 102, "subscribe:订阅失败")
			return
		}
	}

	// 返回
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

func luck(write http.ResponseWriter, request *http.Request) {

	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "luck:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.LuckD
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "luck:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	if data.OpenId == "" {
		utils.CheckErr(write, errors.New("参数错误"), 102, "luck:参数错误")
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	s := strconv.Itoa(getNow())
	// 统计制作食物次数
	keyDay := utils.Config.PkgName + "_luck_" + s
	_, resErr := rc.Do("INCR", keyDay)
	utils.CheckErr(write, resErr, 103, "luck:更新type luck redis失败")
	if resErr != nil {
		return
	}

	if data.Box > 0 {
		// 获取仓库数量
		foodServer := model.NewFoodServer()
		stockStr, err := foodServer.GetStock(data.OpenId)
		utils.CheckErr(write, err, 103, "luck:获取仓库数据失败")
		if err != nil {
			return
		}

		if stockStr != "" {
			// 更新仓库食材
			stockArr := strings.Split(stockStr, ",")
			stockArr[0] = strconv.Itoa(data.Box)

			stockStr = strings.Replace(strings.Trim(fmt.Sprint(stockArr), "[]"), " ", ",", -1)
			err := foodServer.SetStock(data.OpenId, stockStr)
			utils.CheckErr(write, err, 104, "luck:更新数据失败")
			if err != nil {
				return
			}
		}
	}

	if data.Coin > 0 {
		// 更新金币
		err = model.UpdateCoin(data.OpenId, data.Coin)
		utils.CheckErr(write, err, 106, "luck:更新金币失败")
		if err != nil {
			return
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
	}
	returnDa.Returnfunc(write)
}

/*
请求红包碎片
1.判断是否给碎片
2.判断今日领取是否超过30
3.如果超量,返回大于1元的红包
4.记录发放记录并返回
*/
func c1(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "reqCard1:没有收到登录数据")
	if err != nil {
		return
	}

	var cardD model.C1
	err1 := json.Unmarshal(body, &cardD)
	utils.CheckErr(write, err1, 101, "reqCard1:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	flag := utils.Config.RedLock   //   true=终止发送红包碎片
	count := utils.Config.RedLimit // 每天领取碎片上限
	redId := 0

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	s := strconv.Itoa(getNow())

	key := utils.Config.PkgName + "_redCard_" + cardD.OpenId + "_" + s
	if getCount, _ := redis.Int(rc.Do("get", key)); getCount >= count { // 1.判断今日是否领取超过30个
		redId = rRand(4, 7, r)
	} else if flag { // 终止发送
		redId = rRand(4, 7, r)
	} else { // 正常发送
		redId = rRand(1, 7, r)
	}

	key1 := utils.Config.PkgName + "_ttls_c1_" + cardD.OpenId
	_, err2 := redis.Int(rc.Do("get", key1))
	if err2 == nil { // 查到了，证明为连续请求，处理
		utils.CheckErr(write, errors.New("重复请求"), 102, "reqCard1:重复请求")
		return
	} else { // 没查到，第一次请求，放行并设置key
		_, _ = rc.Do("setex", key1, 5, 0)
	}

	key2 := utils.Config.PkgName + "_c1_log_" + cardD.OpenId
	_, _ = rc.Do("set", key2, 0)

	// 返回
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"r_id": redId,
		},
	}
	returnDa.Returnfunc(write)
}

func c2(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "reqCard2:没有收到登录数据")
	if err != nil {
		return
	}

	var cardD model.C2
	err1 := json.Unmarshal(body, &cardD)
	utils.CheckErr(write, err1, 101, "reqCard2:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	s := strconv.Itoa(getNow())

	key := utils.Config.PkgName + "_redCard_" + cardD.OpenId + "_" + s
	// 如果达到领取上限,但是发来的是3毛5毛1块的id,作弊,随机其他不可领取的红包id
	if getCount, _ := redis.Int(rc.Do("get", key)); getCount >= utils.Config.RedLimit && cardD.RId <= 3 {
		cardD.RId = rRand(4, 7, r)
	}

	key1 := utils.Config.PkgName + "_c1_log_" + cardD.OpenId
	val, err2 := redis.Int(rc.Do("get", key1))
	if err2 != nil { // 查到了，证明为连续请求，处理
		utils.CheckErr(write, errors.New("暂时没有卡片"), 102, "reqCard2:暂时没有卡片")
		return
	}

	if val == 1 {
		utils.CheckErr(write, errors.New("重复请求1"), 103, "reqCard2:重复请求!")
		return
	}

	_, _ = rc.Do("set", key1, 1)

	cardId := 0

	if cardD.RId > 0 && cardD.RId <= 7 {

		cardServer := model.NewCardServer()
		var cardInfo model.CardInfo
		// 获取用户数据,如果没有,新建空数据
		cardInfo, err = cardServer.Get(cardD.OpenId)
		if err != nil {
			err = cardServer.Create(cardD.OpenId)
			if err != nil {
				utils.Error(err, "reqCard2:新建碎片记录失败")
			}

			// 再次获取数据,根据红包id获取对应队列
			cardInfo, err = cardServer.Get(cardD.OpenId)
			if err != nil {
				utils.CheckErr(write, err, 104, "reqCard2:获取碎片信息失败")
				return
			}
		}

		queueStr := getQueueStr(cardInfo, cardD.RId)
		// 如果队列为空,新建,如果红包id为123直接添加,如果红包id为其他,需要生成1~3个x点
		if queueStr == "" {
			cardId = int(randInt64(1, 9))
			tmpStr := createStr(cardId, cardD.RId)
			err = cardServer.Update(tmpStr, getColumn(cardD.RId), cardInfo.Id)
			if err != nil {
				utils.CheckErr(write, err, 105, "reqCard2:更新碎片失败")
				return
			}
		} else { // 如果队列不为空,分析队列,如果红包id为123直接添加,如果红包id为其他,随机x外的碎片id
			arr := strings.Split(queueStr, ",")
			if cardD.RId <= 3 {
				// 用于多给重复的碎片
				/*if int(randInt64(1, 10)) <= 5 {
					cardId = 9
				} else {
					cardId = int(randInt64(1, 9))
				}*/

				cardId = rRand(1, 9, r)
			} else {
				for {
					cardId = rRand(1, 9, r)
					if arr[cardId] != "777" {
						break
					}
				}

			}

			tmp, _ := strconv.Atoi(arr[cardId])
			arr[cardId] = strconv.Itoa(tmp + 1)
			newStr := arr2Str(arr)
			err := cardServer.Update(newStr, getColumn(cardD.RId), cardInfo.Id)
			if err != nil {
				utils.CheckErr(write, err, 106, "reqCard2:更新碎片失败")
				return
			}
		}

		if cardId > 0 {
			// 统计每日每个红包发放的碎片数量
			_, err2 := rc.Do("ZINCRBY", utils.Config.PkgName+"_redCard_day_"+s, 1, cardD.RId)
			if err2 != nil {
				utils.Error("reqCard2:update card_day error")
			}

			_, err3 := rc.Do("INCR", utils.Config.PkgName+"_redCardCount_"+s)
			if err3 != nil {
				utils.Error("reqCard2:update cardCount error")
			}

			_, err4 := rc.Do("INCR", key)
			if err4 != nil {
				utils.Error("reqCard2:update redCard error")
			}
		}
	}

	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"red_id":  cardD.RId,
			"card_id": cardId,
		},
	}
	returnDa.Returnfunc(write)
}

func card(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "card:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.C1
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "card:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	cards := make(map[int]string)

	cardServer := model.NewCardServer()
	cardInfo, err := cardServer.Get(data.OpenId)
	if err == nil {
		if cardInfo.C1 != "" {
			cards[1] = cardInfo.C1[2:]
		}
		if cardInfo.C2 != "" {
			cards[2] = cardInfo.C2[2:]
		}
		if cardInfo.C3 != "" {
			cards[3] = cardInfo.C3[2:]
		}
		if cardInfo.C4 != "" {
			tmp := strings.Replace(cardInfo.C4, "777", "0", -1)
			cards[4] = tmp[2:]
		}
		if cardInfo.C5 != "" {
			tmp := strings.Replace(cardInfo.C5, "777", "0", -1)
			cards[5] = tmp[2:]
		}
		if cardInfo.C6 != "" {
			tmp := strings.Replace(cardInfo.C6, "777", "0", -1)
			cards[6] = tmp[2:]
		}
		if cardInfo.C7 != "" {
			tmp := strings.Replace(cardInfo.C7, "777", "0", -1)
			cards[7] = tmp[2:]
		}
	}

	// 返回
	returnDa := utils.ReturnData{
		Errcode: 0,
		Errmsg:  "is ok",
		Data: Map{
			"card": cards,
		},
	}
	returnDa.Returnfunc(write)
}

/*
兑现碎片红包
1.接收用户id以及红包id
2.判断红包id,>3直接返回卡片不足
3.判断红包碎片是否充足
3.减少卡片记录
4.新建卡片兑换记录
5.根据红包id发给用户相应红包
*/
func exchange(write http.ResponseWriter, request *http.Request) {
	body, err := ioutil.ReadAll(request.Body)
	defer request.Body.Close()
	utils.CheckErr(write, err, 100, "exchange:没有收到登录数据")
	if err != nil {
		return
	}

	var data model.Exchange
	err1 := json.Unmarshal(body, &data)
	utils.CheckErr(write, err1, 101, "exchange:无法解析登录的json数据")
	if err1 != nil {
		return
	}

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	key := utils.Config.PkgName + "_ttl_exchange_" + data.OpenId
	_, err100 := redis.Int(rc.Do("get", key))
	if err100 == nil { // 查到了，证明为连续请求，处理
		return
	} else { // 没查到，第一次请求，放行并设置key
		rc.Do("setex", key, 5, 0)
	}

	// 1.接收用户id以及红包id
	if data.RId <= 0 || data.RId > 7 {
		utils.CheckErr(write, errors.New("参数错误"), 103, "exchange:参数错误")
		return
	}

	// 提现限制：每天只能提现10笔
	drawCardServer := model.NewDrawCardServer()
	count := drawCardServer.GetCountDay(data.OpenId, getNow())
	if count >= 10 {
		utils.CheckErr(write, errors.New("每日仅限兑换10次"), 104, "exchange:每日仅限兑换10次")
		return
	}

	if data.RId > 3 {
		utils.CheckErr(write, errors.New("红包碎片不足,无法兑换"), 105, "exchange:红包碎片不足,无法兑换")
		return
	}

	// 4. 判断平台今日可提现金额是否超过1000元
	sum, _ := drawCardServer.GetSumAllTime(getNow())
	if sum >= 50000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 106, "withdraw:今日提现额度已达上限")
		return
	}

	// 4. 判断用户今日可提现金额是否超过30元
	sum, _ = drawCardServer.GetSumDayTime(data.OpenId, getNow())
	if sum >= 3000 {
		utils.CheckErr(write, errors.New("今日提现额度已达上限"), 107, "withdraw:今日提现额度已达上限")
		return
	}

	// 2.判断各个卡片id是否均>=1
	cardServer := model.NewCardServer()
	cardInfo, err := cardServer.Get(data.OpenId)
	if err != nil {
		utils.CheckErr(write, errors.New("获取红包信息失败"), 108, "exchange:获取红包信息失败")
		return
	}

	queueStr := ""
	switch data.RId {
	case 1:
		queueStr = cardInfo.C1
	case 2:
		queueStr = cardInfo.C2
	case 3:
		queueStr = cardInfo.C3
	}

	if queueStr == "" {
		utils.CheckErr(write, errors.New("该红包没有碎片"), 109, "exchange:该红包没有碎片")
		return
	}

	queue := strings.Split(queueStr, ",")
	if checkRed(queue) == false {
		utils.Info(data.OpenId, "|", queueStr)
		utils.CheckErr(write, errors.New("卡片未集齐"), 111, "exchange:卡片未集齐")
		return
	}

	// todo 4.新建卡片兑换记录
	moneyArr := [4]int{0, 30, 50, 100}
	money := moneyArr[data.RId]

	createTime := getTime()
	w := md5.New()
	_, _ = io.WriteString(w, data.OpenId+strconv.Itoa(createTime)+strconv.Itoa(money))
	sign := fmt.Sprintf("%x", w.Sum(nil))

	// 生成提现记录
	drawInfo := &model.DrawCard{
		OpenId:     data.OpenId,
		Money:      money,
		CreateTime: createTime,
		CreatedDay: getNow(),
		Sign:       sign,
		Name:       data.RId,
	}
	err = drawCardServer.Create(drawInfo)
	if err != nil {
		utils.CheckErr(write, err, 112, "exchange:生成提现记录失败")
		return
	}

	// 5. 关联检测
	unionOpenId, codeNo := checkUnion(data.OpenId)
	if codeNo > 0 {
		utils.CheckErr(write, err, 113, "exchange:系统异常,请重试")
		return
	}
	// 6. 如果已关联,直接调用block接口 提现
	if unionOpenId != "" {
		code, err := drawMahjongFunc(unionOpenId, sign, 1)
		// 判断是否提现成功
		if code != 0 {
			utils.CheckErr(write, err, 110, "提现失败")
			return
		} else {
			returnDa := utils.ReturnData{
				Errcode: 0,
				Errmsg:  "提现成功,请查看微信支付消息!",
			}
			returnDa.Returnfunc(write)
		}
	} else { // 7. 如果未关联,告知并返回前端openid+sign并跳转到block新接口
		returnDa := utils.ReturnData{
			Errcode: 1000,
			Errmsg:  "",
			Data: Map{
				"open_id": data.OpenId,
				"sign":    sign,
				"type":    1,
			},
		}
		returnDa.Returnfunc(write)
	}
}

func test1(write http.ResponseWriter, request *http.Request) {

	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	// todo 4.新建卡片兑换记录
	moneyArr := [4]int{0, 30, 50, 100}
	rid := rRand(2, 3, r)
	money := moneyArr[rid]

	openIds := []string{
		"oyL_q4q5tnAD5d2pnbul-TGUy4Go",
		"oyL_q4t8-4AjKlY_Cz6Q-XyMGRms",
		"oyL_q4igcjYvZJ2j98RkrnX6AVcM",
		"oyL_q4ngkCOLFLXER-kyVHEJGpSI",
		"oyL_q4tGriMLI6bcq-pOxw10FhUY",
		"oyL_q4s9drLikrIiJvMcbFRT67-U",
		"oyL_q4jjl4TrIHzW4EcK_EKykjW0",
		"oyL_q4gHKx30ZtNiXNzshSehT5M8",
		// "oyL_q4oXSG2bzFwgTIMTgraLHvsU",
	}

	openId := openIds[rRand(0, len(openIds)-1, r)]

	// 从池里获取连接
	rc := model.RedisClient.Get()
	// 用完后将连接放回连接池
	defer rc.Close()

	s := strconv.Itoa(getNow())
	key := utils.Config.PkgName + "_test1_" + openId + "_" + s
	num, _ := redis.Int(rc.Do("get", key))

	if num >= 10 {
		return
	}

	createTime := getTime()
	w := md5.New()
	_, _ = io.WriteString(w, openId+strconv.Itoa(createTime)+strconv.Itoa(money))
	sign := fmt.Sprintf("%x", w.Sum(nil))

	// 生成提现记录
	drawInfo := &model.DrawCard{
		OpenId:     openId,
		Money:      money,
		CreateTime: createTime,
		CreatedDay: getNow(),
		Sign:       sign,
		Name:       rid,
	}
	drawCardServer := model.NewDrawCardServer()
	err := drawCardServer.Create(drawInfo)
	if err != nil {
		utils.CheckErr(write, err, 101, "test1:生成提现记录失败")
		return
	}

	// 5. 关联检测
	unionOpenId, codeNo := checkUnion(openId)
	if codeNo > 0 {
		utils.CheckErr(write, err, 102, "test1:系统异常,请重试")
		return
	}
	// 6. 如果已关联,直接调用block接口 提现
	if unionOpenId != "" {
		code, err := drawMahjongFunc(unionOpenId, sign, 1)
		// 判断是否提现成功
		if code != 0 {
			utils.CheckErr(write, err, 110, "提现失败")
			return
		} else {
			_, resErr := rc.Do("INCR", key)
			utils.CheckErr(write, resErr, 111, "test1:更新type redis失败")
			if resErr != nil {
				return
			}
			returnDa := utils.ReturnData{
				Errcode: 0,
				Errmsg:  "测试成功",
			}
			returnDa.Returnfunc(write)
		}
	}
}
